aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--data/Makefile.am11
-rw-r--r--data/canonical-logo.pngbin0 -> 4272 bytes
-rw-r--r--data/icons/Makefile.am6
-rw-r--r--data/icons/hicolor_apps_16x16_im-skype.pngbin0 -> 364 bytes
-rw-r--r--data/icons/hicolor_apps_22x22_im-skype.pngbin0 -> 438 bytes
-rw-r--r--data/icons/hicolor_apps_24x24_im-skype.pngbin0 -> 403 bytes
-rw-r--r--data/icons/hicolor_apps_32x32_im-skype.pngbin0 -> 557 bytes
-rw-r--r--data/icons/hicolor_apps_48x48_im-skype.pngbin0 -> 698 bytes
-rw-r--r--data/icons/hicolor_apps_scalable_im-skype.svg76
-rw-r--r--data/plugged-into-skype.pngbin0 -> 4045 bytes
-rw-r--r--data/skype-eula.txt1
-rw-r--r--extensions/Account_Interface_External_Password_Storage.xml52
-rw-r--r--extensions/Connection_Interface_Privacy_Settings.xml123
-rw-r--r--extensions/Makefile.am2
-rw-r--r--extensions/misc.xml2
-rw-r--r--libempathy-gtk/Makefile.am3
-rw-r--r--libempathy-gtk/empathy-account-widget-private.h46
-rw-r--r--libempathy-gtk/empathy-account-widget-skype.c1042
-rw-r--r--libempathy-gtk/empathy-account-widget-skype.h38
-rw-r--r--libempathy-gtk/empathy-account-widget-skype.ui588
-rw-r--r--libempathy-gtk/empathy-account-widget.c61
-rw-r--r--libempathy-gtk/empathy-call-utils.c2
-rw-r--r--libempathy-gtk/empathy-chat-text-view.c41
-rw-r--r--libempathy-gtk/empathy-chat-text-view.h2
-rw-r--r--libempathy-gtk/empathy-chat.c52
-rw-r--r--libempathy-gtk/empathy-contact-blocking-dialog.ui10
-rw-r--r--libempathy-gtk/empathy-contact-widget.c6
-rw-r--r--libempathy-gtk/empathy-individual-view.c18
-rw-r--r--libempathy-gtk/empathy-individual-widget.c6
-rw-r--r--libempathy-gtk/empathy-location-manager.c12
-rw-r--r--libempathy-gtk/empathy-log-window.c51
-rw-r--r--libempathy-gtk/empathy-theme-adium.c6
-rw-r--r--libempathy-gtk/empathy-theme-boxes.c2
-rw-r--r--libempathy/empathy-contact.c22
-rw-r--r--libempathy/empathy-ft-handler.c4
-rw-r--r--libempathy/empathy-message.c207
-rw-r--r--libempathy/empathy-message.h21
-rw-r--r--libempathy/empathy-time.c122
-rw-r--r--libempathy/empathy-time.h10
-rw-r--r--libempathy/empathy-tp-chat.c365
-rw-r--r--libempathy/empathy-tp-chat.h3
-rw-r--r--libempathy/empathy-tp-file.c2
-rw-r--r--libempathy/empathy-utils.c3
-rw-r--r--po/POTFILES.in2
-rw-r--r--src/empathy-account-assistant.c10
-rw-r--r--src/empathy-accounts-dialog.c36
-rw-r--r--src/empathy-chat-manager.c10
-rw-r--r--src/empathy-event-manager.c2
-rw-r--r--src/empathy-map-view.c16
m---------telepathy-yell0
50 files changed, 2497 insertions, 597 deletions
diff --git a/data/Makefile.am b/data/Makefile.am
index a0c715550..b7fb23e9d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -55,6 +55,15 @@ clientfile_DATA = \
htmldir = $(datadir)/empathy
html_DATA = Template.html
+pixmapsdir = $(datadir)/empathy
+pixmaps_DATA = \
+ canonical-logo.png \
+ plugged-into-skype.png \
+ $(NULL)
+
+euladir = $(datadir)/empathy
+eula_DATA = skype-eula.txt
+
EXTRA_DIST = \
$(convert_DATA) \
$(desktop_in_files) \
@@ -65,6 +74,8 @@ EXTRA_DIST = \
$(clientfile_DATA) \
$(servicefile_in_files) \
$(gsettings_files) \
+ $(pixmaps_DATA) \
+ $(eula_DATA) \
$(NULL)
DISTCLEANFILES = \
diff --git a/data/canonical-logo.png b/data/canonical-logo.png
new file mode 100644
index 000000000..3a1804128
--- /dev/null
+++ b/data/canonical-logo.png
Binary files differ
diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
index 2e38cc542..d74a9c900 100644
--- a/data/icons/Makefile.am
+++ b/data/icons/Makefile.am
@@ -44,6 +44,7 @@ private_icons = \
hicolor_apps_16x16_im-mxit.png \
hicolor_apps_16x16_im-myspace.png \
hicolor_apps_16x16_im-sametime.png \
+ hicolor_apps_16x16_im-skype.png \
hicolor_apps_16x16_im-yahoo.png \
hicolor_apps_16x16_im-zephyr.png \
hicolor_apps_22x22_im-aim.png \
@@ -65,6 +66,7 @@ private_icons = \
hicolor_apps_22x22_im-mxit.png \
hicolor_apps_22x22_im-myspace.png \
hicolor_apps_22x22_im-sametime.png \
+ hicolor_apps_22x22_im-skype.png \
hicolor_apps_22x22_im-yahoo.png \
hicolor_apps_22x22_im-zephyr.png \
hicolor_apps_24x24_im-aim.png \
@@ -85,6 +87,7 @@ private_icons = \
hicolor_apps_24x24_im-mxit.png \
hicolor_apps_24x24_im-myspace.png \
hicolor_apps_24x24_im-sametime.png \
+ hicolor_apps_24x24_im-skype.png \
hicolor_apps_24x24_im-yahoo.png \
hicolor_apps_24x24_im-zephyr.png \
hicolor_apps_32x32_im-aim.png \
@@ -105,6 +108,7 @@ private_icons = \
hicolor_apps_32x32_im-mxit.png \
hicolor_apps_32x32_im-myspace.png \
hicolor_apps_32x32_im-sametime.png \
+ hicolor_apps_32x32_im-skype.png \
hicolor_apps_32x32_im-yahoo.png \
hicolor_apps_32x32_im-zephyr.png \
hicolor_apps_48x48_im-aim.png \
@@ -126,6 +130,7 @@ private_icons = \
hicolor_apps_48x48_im-mxit.png \
hicolor_apps_48x48_im-myspace.png \
hicolor_apps_48x48_im-sametime.png \
+ hicolor_apps_48x48_im-skype.png \
hicolor_apps_48x48_im-yahoo.png \
hicolor_apps_48x48_im-zephyr.png \
hicolor_apps_scalable_im-aim.svg \
@@ -146,6 +151,7 @@ private_icons = \
hicolor_apps_scalable_im-mxit.svg \
hicolor_apps_scalable_im-myspace.svg \
hicolor_apps_scalable_im-sametime.svg \
+ hicolor_apps_scalable_im-skype.svg \
hicolor_apps_scalable_im-yahoo.svg \
hicolor_apps_scalable_im-zephyr.svg \
hicolor_status_16x16_user-available.png \
diff --git a/data/icons/hicolor_apps_16x16_im-skype.png b/data/icons/hicolor_apps_16x16_im-skype.png
new file mode 100644
index 000000000..186d8c2f6
--- /dev/null
+++ b/data/icons/hicolor_apps_16x16_im-skype.png
Binary files differ
diff --git a/data/icons/hicolor_apps_22x22_im-skype.png b/data/icons/hicolor_apps_22x22_im-skype.png
new file mode 100644
index 000000000..239f697cd
--- /dev/null
+++ b/data/icons/hicolor_apps_22x22_im-skype.png
Binary files differ
diff --git a/data/icons/hicolor_apps_24x24_im-skype.png b/data/icons/hicolor_apps_24x24_im-skype.png
new file mode 100644
index 000000000..d4e78cafb
--- /dev/null
+++ b/data/icons/hicolor_apps_24x24_im-skype.png
Binary files differ
diff --git a/data/icons/hicolor_apps_32x32_im-skype.png b/data/icons/hicolor_apps_32x32_im-skype.png
new file mode 100644
index 000000000..80721f871
--- /dev/null
+++ b/data/icons/hicolor_apps_32x32_im-skype.png
Binary files differ
diff --git a/data/icons/hicolor_apps_48x48_im-skype.png b/data/icons/hicolor_apps_48x48_im-skype.png
new file mode 100644
index 000000000..a97b6c13d
--- /dev/null
+++ b/data/icons/hicolor_apps_48x48_im-skype.png
Binary files differ
diff --git a/data/icons/hicolor_apps_scalable_im-skype.svg b/data/icons/hicolor_apps_scalable_im-skype.svg
new file mode 100644
index 000000000..3b07a1cf2
--- /dev/null
+++ b/data/icons/hicolor_apps_scalable_im-skype.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg2991"
+ version="1.1"
+ inkscape:version="0.48.1 r9760"
+ sodipodi:docname="hicolor_apps_scalable_im-skype.svg">
+ <defs
+ id="defs2993" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7"
+ inkscape:cx="-30.428571"
+ inkscape:cy="35.428571"
+ inkscape:current-layer="svg2991"
+ showgrid="true"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1143"
+ inkscape:window-x="1280"
+ inkscape:window-y="26"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata2996">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Emilio Pozuelo Monfort</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Collabora Ltd.</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ sodipodi:type="arc"
+ style="fill:#00aeef;fill-opacity:1"
+ id="path2999"
+ sodipodi:cx="23.142857"
+ sodipodi:cy="26.285715"
+ sodipodi:rx="13.857142"
+ sodipodi:ry="13.857142"
+ d="m 36.999999,26.285715 a 13.857142,13.857142 0 1 1 -27.7142849,0 13.857142,13.857142 0 1 1 27.7142849,0 z"
+ transform="translate(0.71428571,-1.2857143)" />
+ </g>
+</svg>
diff --git a/data/plugged-into-skype.png b/data/plugged-into-skype.png
new file mode 100644
index 000000000..670eda7ba
--- /dev/null
+++ b/data/plugged-into-skype.png
Binary files differ
diff --git a/data/skype-eula.txt b/data/skype-eula.txt
new file mode 100644
index 000000000..2b70dd2ca
--- /dev/null
+++ b/data/skype-eula.txt
@@ -0,0 +1 @@
+END USER LICENSE AGREEMENT
diff --git a/extensions/Account_Interface_External_Password_Storage.xml b/extensions/Account_Interface_External_Password_Storage.xml
new file mode 100644
index 000000000..71a542428
--- /dev/null
+++ b/extensions/Account_Interface_External_Password_Storage.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" ?>
+<node name="/Account_Interface_External_Password_Storage"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+
+ <tp:copyright>Copyright © 2011 Collabora Ltd.</tp:copyright>
+ <tp:license xmlns="http://www.w3.org/1999/xhtml">
+ <p>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.</p>
+
+ <p>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.</p>
+
+ <p>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 Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.</p>
+ </tp:license>
+
+ <interface name="org.freedesktop.Telepathy.Account.Interface.ExternalPasswordStorage.DRAFT"
+ tp:causes-havoc="experimental">
+ <tp:added version="0.21.10">(draft 1)</tp:added>
+ <tp:requires interface="org.freedesktop.Telepathy.Account"/>
+
+ <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
+ <p>An interface for Accounts whose passwords are stored externally and
+ SHOULD NOT be stored by either the <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy">AccountManager</tp:dbus-ref> nor
+ any <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Channel.Type">ServerAuthentication</tp:dbus-ref>
+ handler.</p>
+ </tp:docstring>
+
+ <method name="ForgetPassword" tp:name-for-bindings="Forget_Password">
+ <tp:docstring>
+ <p>Clears any saved password associated with this account.</p>
+ </tp:docstring>
+ </method>
+
+ <property name="PasswordSaved"
+ tp:name-for-bindings="Password_Saved"
+ type="b" access="read">
+ <tp:docstring>
+ <p>Indicates whether the account has a saved password or not.</p>
+ </tp:docstring>
+ </property>
+
+ </interface>
+</node>
diff --git a/extensions/Connection_Interface_Privacy_Settings.xml b/extensions/Connection_Interface_Privacy_Settings.xml
new file mode 100644
index 000000000..47bb03270
--- /dev/null
+++ b/extensions/Connection_Interface_Privacy_Settings.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" ?>
+<node name="/Connection_Interface_Privacy_Settings"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
+ <tp:copyright>Copyright &#x00a9; 2010 Collabora Ltd.</tp:copyright>
+ <tp:license xmlns="http://www.w3.org/1999/xhtml">
+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
+Library 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ </tp:license>
+
+ <interface
+ name="uk.co.Collabora.Telepathy.Psyke.Connection.Interface.PrivacySettings">
+
+ <tp:docstring>
+ Privacy Setting Connection properties for telepathy-psyke.
+ </tp:docstring>
+
+ <tp:enum name="Privacy_Setting" type="u"
+ value_prefix="Privacy_Setting">
+ <tp:docstring>
+ Ordering of these values in SkypeKit is inconsistent. Always switch
+ for the values you want.
+ </tp:docstring>
+
+ <tp:enumvalue suffix="Nobody" value="0">
+ <tp:docstring>
+ No users (not available for all properties).
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Contacts" value="1">
+ <tp:docstring>
+ Users on the contact list.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Anyone" value="2">
+ <tp:docstring>
+ All users.
+ </tp:docstring>
+ </tp:enumvalue>
+ <tp:enumvalue suffix="Known_Numbers" value="3">
+ <tp:docstring>
+ Known numbers (not available for all properties).
+ </tp:docstring>
+ </tp:enumvalue>
+ </tp:enum>
+
+ <property name="AllowTextChannelsFrom"
+ tp:name-for-bindings="Allow_Text_Channels_From"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ From whom to allow incoming Text channels.
+ </tp:docstring>
+ </property>
+
+ <property name="AllowCallChannelsFrom"
+ tp:name-for-bindings="Allow_Call_Channels_From"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ From whom to allow incoming Call channels.
+ </tp:docstring>
+ </property>
+
+ <!-- FIXME: this property is difficult to implement, disable for now
+ <property name="AllowVideoFrom"
+ tp:name-for-bindings="Allow_Video_From"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ From whom to automatically enable video.
+ </tp:docstring>
+ </property>
+ -->
+
+ <property name="AllowOutsideCallsFrom"
+ tp:name-for-bindings="Allow_Outside_Calls_From"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ From whom to receive outside calls.
+ </tp:docstring>
+ </property>
+
+ <property name="ShowMyAvatarTo"
+ tp:name-for-bindings="Show_My_Avatar_To"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ To whom to show my avatar.
+ </tp:docstring>
+ </property>
+
+ <property name="ShowMyWebStatus"
+ tp:name-for-bindings="Show_My_Web_Status"
+ type="b" access="readwrite">
+ <tp:docstring>
+ Whether or not to show my status on the web.
+ </tp:docstring>
+ </property>
+
+ <property name="ShowIHaveVideoTo"
+ tp:name-for-bindings="Show_I_Have_Video_To"
+ type="u" tp:type="Privacy_Setting"
+ access="readwrite">
+ <tp:docstring>
+ To whom I should advertise video (Nobody, Contacts, Anyone).
+ </tp:docstring>
+ </property>
+
+ </interface>
+
+</node>
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 30adce0da..87fbca4b4 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -14,9 +14,11 @@ EXTRA_DIST = \
misc.xml \
Debug.xml \
Logger.xml \
+ Account_Interface_External_Password_Storage.xml \
Authentication_TLS_Certificate.xml \
Channel_Interface_Credentials_Storage.xml \
Channel_Type_Server_TLS_Connection.xml \
+ Connection_Interface_Privacy_Settings.xml \
$(NULL)
noinst_LTLIBRARIES = libemp-extensions.la
diff --git a/extensions/misc.xml b/extensions/misc.xml
index 6a137ef06..0686d564c 100644
--- a/extensions/misc.xml
+++ b/extensions/misc.xml
@@ -6,8 +6,10 @@
<xi:include href="Debug.xml" />
<xi:include href="Logger.xml" />
+<xi:include href="Account_Interface_External_Password_Storage.xml" />
<xi:include href="Authentication_TLS_Certificate.xml" />
<xi:include href="Channel_Interface_Credentials_Storage.xml" />
<xi:include href="Channel_Type_Server_TLS_Connection.xml" />
+<xi:include href="Connection_Interface_Privacy_Settings.xml" />
</tp:spec>
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index 50b5dc547..28bfbe07c 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -35,6 +35,7 @@ libempathy_gtk_handwritten_source = \
empathy-account-widget-irc.c \
empathy-account-widget-private.h \
empathy-account-widget-sip.c \
+ empathy-account-widget-skype.c \
empathy-account-widget.c \
empathy-avatar-chooser.c \
empathy-avatar-image.c \
@@ -97,6 +98,7 @@ libempathy_gtk_headers = \
empathy-account-chooser.h \
empathy-account-widget-irc.h \
empathy-account-widget-sip.h \
+ empathy-account-widget-skype.h \
empathy-account-widget.h \
empathy-avatar-chooser.h \
empathy-avatar-image.h \
@@ -202,6 +204,7 @@ ui_DATA = \
empathy-account-widget-yahoo.ui \
empathy-account-widget-groupwise.ui \
empathy-account-widget-aim.ui \
+ empathy-account-widget-skype.ui \
empathy-status-preset-dialog.ui \
empathy-log-window.ui \
empathy-chat.ui \
diff --git a/libempathy-gtk/empathy-account-widget-private.h b/libempathy-gtk/empathy-account-widget-private.h
index d15aa550d..a23a947f1 100644
--- a/libempathy-gtk/empathy-account-widget-private.h
+++ b/libempathy-gtk/empathy-account-widget-private.h
@@ -26,6 +26,8 @@
#include <glib.h>
#include <gtk/gtk.h>
+#include "empathy-account-widget-irc.h"
+
G_BEGIN_DECLS
struct _EmpathyAccountWidgetUIDetails {
@@ -43,6 +45,50 @@ struct _EmpathyAccountWidgetUIDetails {
gpointer user_data);
};
+typedef struct {
+ EmpathyAccountSettings *settings;
+
+ GtkWidget *table_common_settings;
+ GtkWidget *apply_button;
+ GtkWidget *cancel_button;
+ GtkWidget *entry_password;
+ GtkWidget *spinbutton_port;
+ GtkWidget *enabled_checkbox;
+ GtkWidget *radiobutton_reuse;
+
+ gboolean simple;
+ gboolean enabled;
+
+ gboolean contains_pending_changes;
+
+ /* 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;
+
+ /* whether there are any other real accounts. Necessary so we know whether
+ * it's safe to dismiss this widget in some cases (eg, whether the Cancel
+ * button should be sensitive) */
+ gboolean other_accounts_exist;
+
+ /* if TRUE, the GTK+ destroy signal has been fired and so the widgets
+ * embedded in this account widget can't be used any more
+ * workaround because some async callbacks can be called after the
+ * widget has been destroyed */
+ gboolean destroyed;
+
+ TpAccountManager *account_manager;
+
+ GtkWidget *param_account_widget;
+ GtkWidget *param_password_widget;
+
+ gboolean automatic_change;
+ GtkWidget *remember_password_widget;
+
+ /* Used only for IRC accounts */
+ EmpathyIrcNetworkChooser *irc_network_chooser;
+
+ gboolean dispose_run;
+} EmpathyAccountWidgetPriv;
void empathy_account_widget_handle_params (EmpathyAccountWidget *self,
const gchar *first_widget,
diff --git a/libempathy-gtk/empathy-account-widget-skype.c b/libempathy-gtk/empathy-account-widget-skype.c
new file mode 100644
index 000000000..9b8e6270f
--- /dev/null
+++ b/libempathy-gtk/empathy-account-widget-skype.c
@@ -0,0 +1,1042 @@
+/*
+ * Copyright (C) 2011 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: Danielle Madeley <danielle.madeley@collabora.co.uk>
+ * Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <extensions/extensions.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-server-sasl-handler.h>
+
+#include "empathy-account-widget-skype.h"
+#include "empathy-account-widget-private.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
+#include <libempathy/empathy-debug.h>
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget)
+
+typedef struct
+{
+ TpAccount *account;
+ TpChannel *channel;
+ char *password;
+ gboolean remember;
+} ObserveChannelsData;
+
+static ObserveChannelsData *
+observe_channels_data_new (TpAccount *account,
+ TpChannel *channel,
+ const char *password,
+ gboolean remember)
+{
+ ObserveChannelsData *data = g_slice_new0 (ObserveChannelsData);
+
+ data->account = g_object_ref (account);
+ data->channel = g_object_ref (channel);
+ data->password = g_strdup (password);
+ data->remember = remember;
+
+ return data;
+}
+
+static void
+observe_channels_data_free (ObserveChannelsData *data)
+{
+ g_object_unref (data->account);
+ g_object_unref (data->channel);
+ g_free (data->password);
+
+ g_slice_free (ObserveChannelsData, data);
+}
+
+static void
+auth_observer_sasl_handler_invalidated (EmpathyServerSASLHandler *sasl_handler,
+ gpointer user_data)
+{
+ DEBUG ("SASL Handler done");
+
+ g_object_unref (sasl_handler);
+}
+
+static void
+auth_observer_new_sasl_handler_cb (GObject *obj,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ObserveChannelsData *data = user_data;
+ EmpathyServerSASLHandler *sasl_handler;
+ GError *error = NULL;
+
+ sasl_handler = empathy_server_sasl_handler_new_finish (result, &error);
+ if (error != NULL)
+ {
+ DEBUG ("Failed to create SASL handler: %s", error->message);
+
+ tp_channel_close_async (data->channel, NULL, NULL);
+
+ g_error_free (error);
+ goto finally;
+ }
+
+ DEBUG ("providing password, remember = %s", data->remember ? "yes" : "no");
+
+ g_signal_connect (sasl_handler, "invalidated",
+ G_CALLBACK (auth_observer_sasl_handler_invalidated), NULL);
+ empathy_server_sasl_handler_provide_password (sasl_handler,
+ data->password, data->remember);
+
+finally:
+ observe_channels_data_free (data);
+}
+
+static void
+auth_observer_claim_cb (GObject *dispatch_operation,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ObserveChannelsData *data = user_data;
+ GError *error = NULL;
+
+ if (!tp_channel_dispatch_operation_claim_finish (
+ TP_CHANNEL_DISPATCH_OPERATION (dispatch_operation), result, &error))
+ {
+ DEBUG ("Failed to claim auth channel: %s", error->message);
+
+ g_error_free (error);
+ observe_channels_data_free (data);
+ return;
+ }
+
+ empathy_server_sasl_handler_new_async (data->account, data->channel,
+ auth_observer_new_sasl_handler_cb, data);
+}
+
+static void
+auth_observer_observe_channels (TpSimpleObserver *auth_observer,
+ TpAccount *account,
+ TpConnection *connection,
+ GList *channels,
+ TpChannelDispatchOperation *dispatch_operation,
+ GList *requests,
+ TpObserveChannelsContext *context,
+ gpointer user_data)
+{
+ TpChannel *channel;
+ GHashTable *props;
+ GStrv available_mechanisms;
+ GtkWidget *password_entry = user_data;
+ const char *password = NULL;
+ gboolean remember;
+
+ /* we only do this for Psyke */
+ if (tp_strdiff (
+ tp_connection_get_connection_manager_name (connection),
+ "psyke"))
+ goto except;
+
+ /* can only deal with one channel */
+ if (g_list_length (channels) != 1)
+ goto except;
+
+ channel = channels->data;
+ props = tp_channel_borrow_immutable_properties (channel);
+ available_mechanisms = tp_asv_get_boxed (props,
+ TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_AVAILABLE_MECHANISMS,
+ G_TYPE_STRV);
+
+ /* must support X-TELEPATHY-PASSWORD */
+ if (!tp_strv_contains ((const char * const *) available_mechanisms,
+ "X-TELEPATHY-PASSWORD"))
+ goto except;
+
+ /* do we have a password */
+ if (g_object_get_data (G_OBJECT (password_entry), "fake-password") == NULL)
+ password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+
+ if (tp_str_empty (password))
+ goto except;
+
+ /* do we want to remember it */
+ remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+ g_object_get_data (G_OBJECT (password_entry), "remember-password")));
+
+ DEBUG ("claiming auth channel");
+
+ tp_channel_dispatch_operation_claim_async (dispatch_operation,
+ auth_observer_claim_cb,
+ observe_channels_data_new (account, channel, password, remember));
+
+except:
+ tp_observe_channels_context_accept (context);
+}
+
+static TpBaseClient *
+auth_observer_new (GtkWidget *password_entry)
+{
+ TpDBusDaemon *dbus;
+ TpBaseClient *auth_observer;
+ GError *error = NULL;
+
+ dbus = tp_dbus_daemon_dup (&error);
+
+ if (error != NULL)
+ {
+ g_warning ("Failed to get DBus daemon: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ auth_observer = tp_simple_observer_new (dbus, FALSE, "Empathy.PsykePreAuth",
+ FALSE, auth_observer_observe_channels, password_entry, NULL);
+
+ tp_base_client_set_observer_delay_approvers (auth_observer, TRUE);
+ tp_base_client_take_observer_filter (auth_observer, tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE,
+ G_TYPE_STRING,
+ TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION,
+
+ TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD,
+ G_TYPE_STRING,
+ TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION,
+
+ NULL));
+
+ if (!tp_base_client_register (auth_observer, &error))
+ {
+ DEBUG ("Failed to register Psyke pre-auth observer: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (dbus);
+
+ return auth_observer;
+}
+
+enum {
+ PS_COL_ENUM_VALUE,
+ PS_COL_DISPLAY_NAME,
+ NUM_PS_COLS
+};
+
+static void
+account_widget_skype_combo_changed_cb (GtkComboBox *combo,
+ EmpathyAccountWidget *self)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ const char *prop_name = g_object_get_data (G_OBJECT (combo), "dbus-property");
+ TpConnection *conn;
+ EmpPrivacySetting prop_value;
+ GtkTreeIter iter;
+ GValue value = { 0, };
+
+ gtk_combo_box_get_active_iter (combo, &iter);
+ gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
+ PS_COL_ENUM_VALUE, &prop_value,
+ -1);
+
+ DEBUG ("Combo changed: %s", prop_name);
+
+ g_value_init (&value, G_TYPE_UINT);
+ g_value_set_uint (&value, prop_value);
+
+ conn = tp_account_get_connection (
+ empathy_account_settings_get_account (priv->settings));
+ tp_cli_dbus_properties_call_set (conn, -1,
+ EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS,
+ prop_name, &value, NULL, NULL, NULL, NULL);
+
+ g_value_unset (&value);
+}
+
+static void
+account_widget_skype_toggle_changed_cb (GtkToggleButton *toggle,
+ EmpathyAccountWidget *self)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ const char *prop_name = g_object_get_data (G_OBJECT (toggle),
+ "dbus-property");
+ TpConnection *conn;
+ GValue value = { 0, };
+
+ DEBUG ("Toggle changed: %s", prop_name);
+
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, gtk_toggle_button_get_active (toggle));
+
+ conn = tp_account_get_connection (
+ empathy_account_settings_get_account (priv->settings));
+ tp_cli_dbus_properties_call_set (conn, -1,
+ EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS,
+ prop_name, &value, NULL, NULL, NULL, NULL);
+
+ g_value_unset (&value);
+}
+
+static void
+account_widget_skype_set_value (EmpathyAccountWidget *self,
+ GtkWidget *widget,
+ GValue *value)
+{
+ g_return_if_fail (value != NULL);
+
+ if (GTK_IS_COMBO_BOX (widget))
+ {
+ GtkTreeModel *model =
+ gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ guint prop_value;
+ GtkTreeIter iter;
+ gboolean valid;
+
+ g_return_if_fail (G_VALUE_HOLDS_UINT (value));
+
+ prop_value = g_value_get_uint (value);
+
+ g_signal_handlers_block_by_func (widget,
+ account_widget_skype_combo_changed_cb, self);
+
+ for (valid = gtk_tree_model_get_iter_first (model, &iter);
+ valid;
+ valid = gtk_tree_model_iter_next (model, &iter))
+ {
+ guint v;
+
+ gtk_tree_model_get (model, &iter,
+ PS_COL_ENUM_VALUE, &v,
+ -1);
+
+ if (v == prop_value)
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+ break;
+ }
+ }
+
+ g_signal_handlers_unblock_by_func (widget,
+ account_widget_skype_combo_changed_cb, self);
+ }
+ else if (GTK_IS_TOGGLE_BUTTON (widget))
+ {
+ g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (value));
+
+ g_signal_handlers_block_by_func (widget,
+ account_widget_skype_toggle_changed_cb, self);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
+ g_value_get_boolean (value));
+
+ g_signal_handlers_unblock_by_func (widget,
+ account_widget_skype_toggle_changed_cb, self);
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+}
+
+static void
+account_widget_build_skype_get_password_saved_cb (TpProxy *account,
+ const GValue *value,
+ const GError *in_error,
+ gpointer user_data,
+ GObject *password_entry)
+{
+ GtkWidget *remember_password;
+ gboolean password_saved;
+
+ if (in_error != NULL)
+ {
+ DEBUG ("Failed to get PasswordSaved: %s", in_error->message);
+ return;
+ }
+
+ g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (value));
+
+ password_saved = g_value_get_boolean (value);
+
+ DEBUG ("PasswordSaved: %s", password_saved ? "yes" : "no");
+
+ /* don't wipe the password if there's a real value in there */
+ if (g_object_get_data (password_entry, "fake-password") == NULL &&
+ !tp_str_empty (gtk_entry_get_text (GTK_ENTRY (password_entry))))
+ return;
+
+ remember_password =
+ GTK_WIDGET (g_object_get_data (password_entry, "remember-password"));
+
+ gtk_entry_set_text (GTK_ENTRY (password_entry),
+ password_saved ? "xxxxxxxxxxxx": "");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (remember_password),
+ password_saved);
+
+ g_object_set_data (password_entry, "fake-password",
+ GUINT_TO_POINTER (password_saved));
+}
+
+static void
+account_widget_build_skype_account_properties_changed_cb (TpProxy *account,
+ const char *iface,
+ GHashTable *changed,
+ const char **invalidated,
+ gpointer user_data,
+ GObject *password_entry)
+{
+ GValue *value;
+
+ if (tp_strdiff (iface,
+ EMP_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE))
+ return;
+
+ value = g_hash_table_lookup (changed, "PasswordSaved");
+
+ if (value == NULL)
+ return;
+
+ account_widget_build_skype_get_password_saved_cb (account, value, NULL,
+ NULL, password_entry);
+}
+
+static void
+account_widget_skype_additional_apply_forget_passwd_cb (TpProxy *account,
+ const GError *in_error,
+ gpointer user_data,
+ GObject *weak_obj)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (weak_obj);
+
+ if (in_error != NULL)
+ {
+ DEBUG ("Did not forget password: %s", in_error->message);
+ }
+ else
+ {
+ DEBUG ("Password forgot, proceed to reconnect");
+ }
+
+ /* reconnect is required */
+ g_simple_async_result_set_op_res_gboolean (simple, in_error == NULL);
+ g_simple_async_result_complete (simple);
+
+ g_object_unref (simple);
+}
+
+static void
+account_widget_skype_additional_apply_async (EmpathyAccountWidget *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ TpAccount *account = empathy_account_settings_get_account (priv->settings);
+ GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self),
+ callback, user_data, NULL);
+
+ /* we have to forget the password, else psyke won't query for the new one */
+ emp_cli_account_interface_external_password_storage_call_forget_password (
+ TP_PROXY (account), -1,
+ account_widget_skype_additional_apply_forget_passwd_cb,
+ NULL, NULL, G_OBJECT (simple));
+}
+
+static gboolean
+account_widget_build_skype_password_entry_focus (GtkWidget *password_entry,
+ GdkEventFocus *event,
+ EmpathyAccountWidget *self)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ TpAccount *account = empathy_account_settings_get_account (priv->settings);
+
+ if (g_object_get_data (G_OBJECT (password_entry), "fake-password") != NULL)
+ {
+ DEBUG ("Clearing fake password for editing");
+
+ gtk_entry_set_text (GTK_ENTRY (password_entry), "");
+ g_object_set_data (G_OBJECT (password_entry), "fake-password",
+ GUINT_TO_POINTER (FALSE));
+ }
+
+ if (account != NULL && tp_account_is_enabled (account))
+ {
+ DEBUG ("Highlighting Apply/Cancel button");
+
+ self->ui_details->additional_apply_async =
+ account_widget_skype_additional_apply_async;
+ empathy_account_widget_changed (self);
+ }
+
+ return FALSE;
+}
+
+static void
+account_widget_skype_remember_password_toggled (GtkToggleButton *button,
+ EmpathyAccountWidget *self)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ TpAccount *account = empathy_account_settings_get_account (priv->settings);
+
+ /* we only forget the password if the toggle goes inactive */
+ if (gtk_toggle_button_get_active (button))
+ return;
+
+ DEBUG ("forgetting password");
+
+ emp_cli_account_interface_external_password_storage_call_forget_password (
+ TP_PROXY (account), -1, NULL, NULL, NULL, NULL);
+}
+
+static void
+account_widget_build_skype_get_privacy_settings_cb (TpProxy *cm,
+ GHashTable *props,
+ const GError *in_error,
+ gpointer user_data,
+ GObject *weak_obj)
+{
+ EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (weak_obj);
+ GtkBuilder *gui = user_data;
+ guint i;
+
+ static const char *widgets[] = {
+ "allow-text-chats-from",
+ "allow-skype-calls-from",
+ "allow-video-from",
+ "show-my-avatar-to",
+ "show-my-web-status",
+ "show-i-have-video-to"
+ };
+
+ if (in_error != NULL)
+ {
+ GtkWidget *table, *infobar, *label;
+
+ DEBUG ("Failed to get properties: %s", in_error->message);
+
+ table = GTK_WIDGET (gtk_builder_get_object (gui,
+ "privacy-settings-table"));
+ gtk_widget_set_sensitive (table, FALSE);
+
+ infobar = gtk_info_bar_new ();
+ gtk_box_pack_start (
+ GTK_BOX (gtk_builder_get_object (gui, "privacy-settings-vbox")),
+ infobar, FALSE, TRUE, 0);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_ERROR);
+ label = gtk_label_new (_("Failed to retrieve privacy settings."));
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_container_add (GTK_CONTAINER (
+ gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))),
+ label);
+ gtk_widget_show (label);
+
+ return;
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (widgets); i++)
+ {
+ GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (gui, widgets[i]));
+ const char *prop_name = g_object_get_data (G_OBJECT (widget),
+ "dbus-property");
+ GValue *value;
+
+ DEBUG ("Widget '%s' (%s), prop = %s",
+ widgets[i], G_OBJECT_TYPE_NAME (widget), prop_name);
+
+ value = g_hash_table_lookup (props, prop_name);
+ if (value == NULL)
+ {
+ g_warning ("Couldn't get a value for %s", prop_name);
+ continue;
+ }
+
+ account_widget_skype_set_value (self, widget, value);
+ }
+}
+
+static void
+account_widget_skype_properties_changed_cb (TpProxy *conn,
+ const char *interface,
+ GHashTable *props,
+ const char **invalidated,
+ gpointer user_data,
+ GObject *weak_obj)
+{
+ EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (weak_obj);
+ GtkWidget *table = user_data;
+ GHashTableIter iter;
+ const char *prop;
+ GValue *value;
+
+ g_hash_table_iter_init (&iter, props);
+ while (g_hash_table_iter_next (&iter, (gpointer) &prop, (gpointer) &value))
+ {
+ GList *children, *ptr;
+
+ DEBUG ("Property changed: %s", prop);
+
+ /* find this value in the widget tree */
+ children = gtk_container_get_children (GTK_CONTAINER (table));
+
+ for (ptr = children; ptr != NULL; ptr = ptr->next)
+ {
+ GtkWidget *widget = ptr->data;
+ const char *prop_name = g_object_get_data (G_OBJECT (widget),
+ "dbus-property");
+
+ if (!tp_strdiff (prop_name, prop))
+ {
+ DEBUG ("Got child %p (%s)", widget, G_OBJECT_TYPE_NAME (widget));
+
+ account_widget_skype_set_value (self, widget, value);
+ break;
+ }
+ }
+
+ g_list_free (children);
+ }
+}
+
+/**
+ * account_widget_build_skype_setup_combo:
+ * @gui:
+ * @widget:
+ * @first_option: a list of options from the enum, terminated by -1
+ */
+static void
+account_widget_build_skype_setup_combo (EmpathyAccountWidget *self,
+ GtkBuilder *gui,
+ const char *widget,
+ const char *prop_name,
+ int first_option,
+ ...)
+{
+ GtkWidget *combo;
+ GtkListStore *store;
+ va_list var_args;
+ int option;
+
+ static const char *options[NUM_EMP_PRIVACY_SETTINGS] = {
+ N_("No one"),
+ N_("My contacts"),
+ N_("Anyone"),
+ N_("Known Numbers")
+ };
+
+ combo = GTK_WIDGET (gtk_builder_get_object (gui, widget));
+
+ g_return_if_fail (combo != NULL);
+
+ store = gtk_list_store_new (NUM_PS_COLS,
+ G_TYPE_UINT, /* PS_COL_ENUM_VALUE */
+ G_TYPE_STRING /* PS_COL_DISPLAY_NAME */
+ );
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
+
+ va_start (var_args, first_option);
+
+ for (option = first_option; option != -1; option = va_arg (var_args, int))
+ {
+ gtk_list_store_insert_with_values (store, NULL, -1,
+ PS_COL_ENUM_VALUE, option,
+ PS_COL_DISPLAY_NAME, gettext (options[option]),
+ -1);
+ }
+
+ va_end (var_args);
+
+ g_object_set_data (G_OBJECT (combo), "dbus-property", (gpointer) prop_name);
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (account_widget_skype_combo_changed_cb), self);
+}
+
+static void
+account_widget_skype_privacy_settings (GtkWidget *button,
+ EmpathyAccountWidget *self)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ TpConnection *conn;
+ char *filename;
+ GtkBuilder *gui;
+ GtkWidget *dialog, *show_my_web_status, *table, *vbox;
+ GtkWidget *toplevel, *infobar, *label;
+
+ DEBUG ("Loading privacy settings");
+
+ filename = empathy_file_lookup ("empathy-account-widget-skype.ui",
+ "libempathy-gtk");
+ gui = empathy_builder_get_file (filename,
+ "privacy-settings-dialog", &dialog,
+ "privacy-settings-table", &table,
+ "privacy-settings-vbox", &vbox,
+ "show-my-web-status", &show_my_web_status,
+ NULL);
+
+ toplevel = gtk_widget_get_toplevel (self->ui_details->widget);
+ if (gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+
+ /* make the settings insensitive when the account is disconnected */
+ tp_account_bind_connection_status_to_property (
+ empathy_account_settings_get_account (priv->settings),
+ table, "sensitive", FALSE);
+
+ /* set up an informative info bar */
+ infobar = gtk_info_bar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), infobar, FALSE, TRUE, 0);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_INFO);
+ label = gtk_label_new (_("Privacy settings can only be changed while the "
+ "account is connected."));
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_container_add (
+ GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))),
+ label);
+ gtk_widget_show (label);
+ g_object_bind_property (table, "sensitive", infobar, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+ account_widget_build_skype_setup_combo (self, gui,
+ "allow-text-chats-from", "AllowTextChannelsFrom",
+ EMP_PRIVACY_SETTING_ANYONE,
+ EMP_PRIVACY_SETTING_CONTACTS,
+ -1);
+ account_widget_build_skype_setup_combo (self, gui,
+ "allow-skype-calls-from", "AllowCallChannelsFrom",
+ EMP_PRIVACY_SETTING_ANYONE,
+ EMP_PRIVACY_SETTING_CONTACTS,
+ -1);
+ account_widget_build_skype_setup_combo (self, gui,
+ "allow-video-from", "AllowVideoFrom",
+ EMP_PRIVACY_SETTING_ANYONE,
+ EMP_PRIVACY_SETTING_CONTACTS,
+ -1);
+ account_widget_build_skype_setup_combo (self, gui,
+ "show-i-have-video-to", "ShowIHaveVideoTo",
+ EMP_PRIVACY_SETTING_ANYONE,
+ EMP_PRIVACY_SETTING_CONTACTS,
+ EMP_PRIVACY_SETTING_NOBODY,
+ -1);
+ account_widget_build_skype_setup_combo (self, gui,
+ "show-my-avatar-to", "ShowMyAvatarTo",
+ EMP_PRIVACY_SETTING_ANYONE,
+ EMP_PRIVACY_SETTING_CONTACTS,
+ -1);
+
+ g_object_set_data (G_OBJECT (show_my_web_status), "dbus-property",
+ "ShowMyWebStatus");
+ g_signal_connect (show_my_web_status, "toggled",
+ G_CALLBACK (account_widget_skype_toggle_changed_cb), self);
+
+ /* get the current parameter values from psyke */
+ conn = tp_account_get_connection (
+ empathy_account_settings_get_account (priv->settings));
+
+ tp_cli_dbus_properties_call_get_all (conn, -1,
+ EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS,
+ account_widget_build_skype_get_privacy_settings_cb,
+ g_object_ref (gui), g_object_unref,
+ G_OBJECT (self));
+ tp_cli_dbus_properties_connect_to_properties_changed (conn,
+ account_widget_skype_properties_changed_cb,
+ table, NULL, G_OBJECT (self), NULL);
+
+ g_object_unref (gui);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+static void
+account_widget_build_skype_set_pixmap (GtkBuilder *gui,
+ const char *widget,
+ const char *file)
+{
+ GtkImage *image = GTK_IMAGE (gtk_builder_get_object (gui, widget));
+ char *filename = empathy_file_lookup (file, "data");
+
+ gtk_image_set_from_file (image, filename);
+
+ g_free (filename);
+}
+
+void
+empathy_account_widget_build_skype (EmpathyAccountWidget *self,
+ const char *filename)
+{
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ TpAccount *account = empathy_account_settings_get_account (priv->settings);
+ GtkWidget *password_entry, *remember_password;
+
+ if (priv->simple || priv->creating_account)
+ {
+ GtkWidget *skype_info;
+
+ /* if we don't have an account it means we're doing the initial setup */
+ self->ui_details->gui = empathy_builder_get_file (filename,
+ "table_common_skype_settings_setup", &priv->table_common_settings,
+ "vbox_skype_settings_setup", &self->ui_details->widget,
+ "skype-info-vbox", &skype_info,
+ "entry_password_setup", &password_entry,
+ "remember-password-setup", &remember_password,
+ NULL);
+
+ account_widget_build_skype_set_pixmap (self->ui_details->gui,
+ "plugged-into-skype-logo", "plugged-into-skype.png");
+ account_widget_build_skype_set_pixmap (self->ui_details->gui,
+ "canonical-logo", "canonical-logo.png");
+
+ gtk_box_pack_end (GTK_BOX (self->ui_details->widget), skype_info,
+ TRUE, TRUE, 0);
+
+ empathy_account_widget_handle_params (self,
+ "entry_id_setup", "account",
+ NULL);
+
+ self->ui_details->default_focus = g_strdup ("entry_id_setup");
+ }
+ else
+ {
+ GtkWidget *edit_privacy_settings_button, *skype_info;
+
+ self->ui_details->gui = empathy_builder_get_file (filename,
+ "table_common_skype_settings", &priv->table_common_settings,
+ "vbox_skype_settings", &self->ui_details->widget,
+ "skype-info-vbox", &skype_info,
+ "edit-privacy-settings-button", &edit_privacy_settings_button,
+ "entry_password", &password_entry,
+ "remember-password", &remember_password,
+ NULL);
+
+ empathy_builder_connect (self->ui_details->gui, self,
+ "edit-privacy-settings-button", "clicked",
+ account_widget_skype_privacy_settings,
+ "remember-password", "toggled",
+ account_widget_skype_remember_password_toggled,
+ NULL);
+
+ if (account != NULL)
+ tp_account_bind_connection_status_to_property (account,
+ edit_privacy_settings_button, "sensitive", FALSE);
+ else
+ gtk_widget_set_sensitive (edit_privacy_settings_button, FALSE);
+
+ account_widget_build_skype_set_pixmap (self->ui_details->gui,
+ "plugged-into-skype-logo", "plugged-into-skype.png");
+ account_widget_build_skype_set_pixmap (self->ui_details->gui,
+ "canonical-logo", "canonical-logo.png");
+
+ gtk_box_pack_end (GTK_BOX (self->ui_details->widget), skype_info,
+ TRUE, TRUE, 0);
+
+ empathy_account_widget_handle_params (self,
+ "entry_id", "account",
+ NULL);
+
+ self->ui_details->default_focus = g_strdup ("entry_id");
+ }
+
+ /* create the Psyke pre-authentication observer --
+ * tie the lifetime of the observer to the lifetime of the widget */
+ g_object_set_data_full (G_OBJECT (self->ui_details->widget), "auth-observer",
+ auth_observer_new (password_entry), g_object_unref);
+ g_object_set_data (G_OBJECT (password_entry), "remember-password",
+ remember_password);
+
+ g_object_bind_property (remember_password, "active",
+ password_entry, "sensitive", G_BINDING_SYNC_CREATE);
+
+ /* find out if we know the password */
+ if (account != NULL && tp_proxy_has_interface_by_id (account,
+ EMP_IFACE_QUARK_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE))
+ {
+ tp_cli_dbus_properties_call_get (account, -1,
+ EMP_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE,
+ "PasswordSaved",
+ account_widget_build_skype_get_password_saved_cb,
+ NULL, NULL, G_OBJECT (password_entry));
+ tp_cli_dbus_properties_connect_to_properties_changed (account,
+ account_widget_build_skype_account_properties_changed_cb,
+ NULL, NULL, G_OBJECT (password_entry), NULL);
+ }
+
+ /* if the user changes the password, it's probably no longer a fake
+ * password */
+ g_signal_connect (password_entry, "focus-in-event",
+ G_CALLBACK (account_widget_build_skype_password_entry_focus), self);
+}
+
+gboolean
+empathy_account_widget_skype_show_eula (GtkWindow *parent)
+{
+ GtkWidget *dialog, *textview, *vbox, *scrolledwindow;
+ GtkTextBuffer *buffer;
+ gchar *filename, *l10n_filename;
+ const gchar * const * langs;
+ GError *error = NULL;
+ gchar *eula;
+ gint result;
+ gsize len;
+ gint i;
+
+ filename = empathy_file_lookup ("skype-eula.txt", "data");
+
+ langs = g_get_language_names ();
+
+ for (i = 0; langs[i] != NULL; i++)
+ {
+ l10n_filename = g_strconcat (filename, ".", langs[i], NULL);
+ g_file_get_contents (l10n_filename, &eula, &len, NULL);
+ g_free (l10n_filename);
+
+ if (eula != NULL)
+ break;
+ }
+
+ if (eula == NULL)
+ {
+ DEBUG ("Could not open translated Skype EULA");
+ g_file_get_contents (filename, &eula, &len, &error);
+ }
+
+ g_free (filename);
+
+ if (error != NULL)
+ {
+ g_warning ("Could not open Skype EULA: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ dialog = gtk_dialog_new_with_buttons (_("End User License Agreement"),
+ parent, GTK_DIALOG_MODAL,
+ _("Decline"), GTK_RESPONSE_CANCEL,
+ _("Accept"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ buffer = gtk_text_buffer_new (NULL);
+ gtk_text_buffer_set_text (buffer, eula, len);
+ g_free (eula);
+ textview = gtk_text_view_new_with_buffer (buffer);
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD_CHAR);
+
+ vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_add_with_viewport (
+ GTK_SCROLLED_WINDOW (scrolledwindow), textview);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 250);
+ gtk_widget_show_all (dialog);
+
+ result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ gtk_widget_destroy (dialog);
+
+ return (result == GTK_RESPONSE_ACCEPT);
+}
+
+static gboolean
+is_other_psyke_account (TpAccount *ours,
+ TpAccount *other)
+{
+ if (ours == NULL)
+ return TRUE;
+
+ return (tp_strdiff (
+ tp_proxy_get_object_path (ours),
+ tp_proxy_get_object_path (other)) &&
+ tp_account_is_enabled (other) &&
+ !tp_strdiff (tp_account_get_connection_manager (other), "psyke"));
+}
+
+gboolean
+empathy_accounts_dialog_skype_disable_other_accounts (TpAccount *account,
+ GtkWindow *parent)
+{
+ TpAccountManager *am = tp_account_manager_dup ();
+ GList *accounts, *ptr;
+ gboolean other_psyke_accounts = FALSE;
+
+ /* check if any other psyke accounts are enabled */
+ accounts = tp_account_manager_get_valid_accounts (am);
+
+ for (ptr = accounts; ptr != NULL; ptr = ptr->next)
+ {
+ TpAccount *a = ptr->data;
+
+ if (is_other_psyke_account (account, a))
+ {
+ other_psyke_accounts = TRUE;
+ break;
+ }
+ }
+
+ g_list_free (accounts);
+
+ if (other_psyke_accounts)
+ {
+#if 0 /* this dialog is a good idea, but currently lacking from the UX spec,
+ * so it's being left out for now */
+ GtkWidget *msg = gtk_message_dialog_new (parent, 0,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ "%s\n\n%s",
+ _("Multiple Skype accounts can not be enabled simultaneously. "
+ "Enabling this Skype account will disable all others."),
+ _("Continue to enable this account?"));
+ int response;
+
+ response = gtk_dialog_run (GTK_DIALOG (msg));
+ gtk_widget_destroy (msg);
+
+ if (response != GTK_RESPONSE_YES)
+ {
+ /* the user chose not to proceed */
+ g_object_unref (am);
+
+ return FALSE;
+ }
+#endif
+
+ /* the user chose to proceed, disable the other accounts */
+ accounts = tp_account_manager_get_valid_accounts (am);
+
+ for (ptr = accounts; ptr != NULL; ptr = ptr->next)
+ {
+ TpAccount *a = ptr->data;
+
+ if (is_other_psyke_account (account, a))
+ {
+ tp_account_set_enabled_async (a, FALSE, NULL, NULL);
+ }
+ }
+
+ g_list_free (accounts);
+ }
+
+ g_object_unref (am);
+
+ return TRUE;
+}
diff --git a/libempathy-gtk/empathy-account-widget-skype.h b/libempathy-gtk/empathy-account-widget-skype.h
new file mode 100644
index 000000000..5ba0c6ed5
--- /dev/null
+++ b/libempathy-gtk/empathy-account-widget-skype.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 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: Danielle Madeley <danielle.madeley@collabora.co.uk>
+ * Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
+ */
+
+#ifndef __EMPATHY_ACCOUNT_WIDGET_SKYPE_H__
+#define __EMPATHY_ACCOUNT_WIDGET_SKYPE_H__
+
+#include <gtk/gtk.h>
+#include <libempathy-gtk/empathy-account-widget.h>
+
+G_BEGIN_DECLS
+
+void empathy_account_widget_build_skype (EmpathyAccountWidget *self,
+ const char *filename);
+gboolean empathy_account_widget_skype_show_eula (GtkWindow *parent);
+gboolean empathy_accounts_dialog_skype_disable_other_accounts (
+ TpAccount *account, GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_ACCOUNT_WIDGET_SKYPE_H__ */
diff --git a/libempathy-gtk/empathy-account-widget-skype.ui b/libempathy-gtk/empathy-account-widget-skype.ui
new file mode 100644
index 000000000..dbea877da
--- /dev/null
+++ b/libempathy-gtk/empathy-account-widget-skype.ui
@@ -0,0 +1,588 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkVBox" id="vbox_skype_settings_setup">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkTable" id="table_common_skype_settings_setup">
+ <property name="visible">True</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label_id">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Skype name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_id_setup</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_id_setup">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_password_setup">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</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="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Don't have a Skype Name?
+Get one at &lt;a href="http://www.skype.com/go/register"&gt;Skype.com&lt;/a&gt;</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>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;a href="https://login.skype.com/account/password-reset-request"&gt;Forgotten your password?&lt;/a&gt;</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">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="remember-password-setup">
+ <property name="label" translatable="yes">Remember pass_word:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkDialog" id="privacy-settings-dialog">
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="skip_pager_hint">True</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="border_width">3</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="privacy-settings-vbox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="privacy-settings-table">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Allow _text chats from:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">allow-text-chats-from</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Allow _calls from:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">allow-skype-calls-from</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">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Allow video _from:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">allow-video-from</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">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Show my profile _picture to:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">show-my-avatar-to</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">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="allow-text-chats-from">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="allow-skype-calls-from">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </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>
+ <object class="GtkComboBox" id="allow-video-from">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext4"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </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>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="show-my-avatar-to">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext5"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </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>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Show whether I have _video to:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">show-i-have-video-to</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">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="show-i-have-video-to">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext3"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </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>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="table2">
+ <property name="visible">True</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Get your own customized button for your website</property>
+ <property name="label" translatable="yes">&lt;a href="http://www.skype.com/intl/en-us/tell-a-friend/get-a-skype-button/"&gt;What's this?&lt;/a&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show-my-web-status">
+ <property name="label" translatable="yes">Show my status in _Web buttons</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span size="x-large" weight="bold"&gt;Privacy Settings&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </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">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">button1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkVBox" id="vbox_skype_settings">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkTable" id="table_common_skype_settings">
+ <property name="visible">True</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>
+ <child>
+ <object class="GtkLabel" id="label_id1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Skype name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_id_setup</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_id">
+ <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="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">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="linkbutton2">
+ <property name="label" translatable="yes">Change Password...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="uri">https://secure.skype.com/account/personal/change-password</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="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="remember-password">
+ <property name="label" translatable="yes">Remember pass_word:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">start</property>
+ <child>
+ <object class="GtkButton" id="edit-privacy-settings-button">
+ <property name="label" translatable="yes">_Privacy Settings...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkVBox" id="skype-info-vbox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="plugged-into-skype-logo">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="width_request">600</property>
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Empathy is plugged into Skype™, allowing free calls to Skype users. Skype is a trademark of Skype Limited or its related companies. This application has not been checked, verified, certified, or otherwise approved or endorsed by Skype Communications S.a.r.l. or any of their related companies.</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImage" id="canonical-logo">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="linkbutton1">
+ <property name="label" translatable="yes">Canonical Support...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="uri">http://canonical.com/support?app=empathy</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Canonical provides technical support for Empathy on Ubuntu.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <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 876f6a436..c78bcb7b8 100644
--- a/libempathy-gtk/empathy-account-widget.c
+++ b/libempathy-gtk/empathy-account-widget.c
@@ -21,6 +21,7 @@
* Martyn Russell <martyn@imendio.com>
* Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
* Jonathan Tellier <jonathan.tellier@gmail.com>
+ * Danielle Madeley <danielle.madeley@collabora.co.uk>
*/
#include <config.h>
@@ -34,6 +35,7 @@
#include <mx-gtk/mx-gtk.h>
#endif /* HAVE_MEEGO */
+
#include <libempathy/empathy-utils.h>
#include <telepathy-glib/account.h>
@@ -46,6 +48,7 @@
#include "empathy-account-widget-private.h"
#include "empathy-account-widget-sip.h"
#include "empathy-account-widget-irc.h"
+#include "empathy-account-widget-skype.h"
#include "empathy-ui-utils.h"
#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
@@ -53,51 +56,6 @@
G_DEFINE_TYPE (EmpathyAccountWidget, empathy_account_widget, G_TYPE_OBJECT)
-typedef struct {
- EmpathyAccountSettings *settings;
-
- GtkWidget *table_common_settings;
- GtkWidget *apply_button;
- GtkWidget *cancel_button;
- GtkWidget *entry_password;
- GtkWidget *spinbutton_port;
- GtkWidget *enabled_checkbox;
- GtkWidget *radiobutton_reuse;
-
- gboolean simple;
- gboolean enabled;
-
- gboolean contains_pending_changes;
-
- /* 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;
-
- /* whether there are any other real accounts. Necessary so we know whether
- * it's safe to dismiss this widget in some cases (eg, whether the Cancel
- * button should be sensitive) */
- gboolean other_accounts_exist;
-
- /* if TRUE, the GTK+ destroy signal has been fired and so the widgets
- * embedded in this account widget can't be used any more
- * workaround because some async callbacks can be called after the
- * widget has been destroyed */
- gboolean destroyed;
-
- TpAccountManager *account_manager;
-
- GtkWidget *param_account_widget;
- GtkWidget *param_password_widget;
-
- gboolean automatic_change;
- GtkWidget *remember_password_widget;
-
- /* Used only for IRC accounts */
- EmpathyIrcNetworkChooser *irc_network_chooser;
-
- gboolean dispose_run;
-} EmpathyAccountWidgetPriv;
-
enum {
PROP_PROTOCOL = 1,
PROP_SETTINGS,
@@ -908,7 +866,9 @@ static void
account_widget_apply_clicked_cb (GtkWidget *button,
EmpathyAccountWidget *self)
{
- account_widget_apply_and_log_in (self);
+ empathy_accounts_dialog_skype_disable_other_accounts (NULL, NULL);
+
+ account_widget_apply_and_log_in (self);
}
static void
@@ -1481,6 +1441,14 @@ account_widget_build_groupwise (EmpathyAccountWidget *self,
}
static void
+account_widget_build_skype (EmpathyAccountWidget *self,
+ const char *filename)
+{
+ empathy_account_widget_build_skype (self, filename);
+}
+
+
+static void
account_widget_destroy_cb (GtkWidget *widget,
EmpathyAccountWidget *self)
{
@@ -1884,6 +1852,7 @@ do_constructed (GObject *obj)
WIDGET (haze, groupwise),
WIDGET (idle, irc),
WIDGET (sofiasip, sip),
+ WIDGET (psyke, skype),
};
cm_name = empathy_account_settings_get_cm (priv->settings);
diff --git a/libempathy-gtk/empathy-call-utils.c b/libempathy-gtk/empathy-call-utils.c
index b362ecaa8..1fe9257cc 100644
--- a/libempathy-gtk/empathy-call-utils.c
+++ b/libempathy-gtk/empathy-call-utils.c
@@ -51,6 +51,8 @@ get_error_display_message (GError *error)
return _("The specified contact is not valid");
case TP_ERROR_EMERGENCY_CALLS_NOT_SUPPORTED:
return _("Emergency calls are not supported on this protocol");
+ case TP_ERROR_INSUFFICIENT_BALANCE:
+ return _("You don't have enough credit in order to place this call");
}
return _("There was an error starting the call");
diff --git a/libempathy-gtk/empathy-chat-text-view.c b/libempathy-gtk/empathy-chat-text-view.c
index c05b92fb9..977530971 100644
--- a/libempathy-gtk/empathy-chat-text-view.c
+++ b/libempathy-gtk/empathy-chat-text-view.c
@@ -49,7 +49,7 @@
#include <libempathy/empathy-debug.h>
/* Number of seconds between timestamps when using normal mode, 5 minutes. */
-#define TIMESTAMP_INTERVAL 300
+#define TIMESTAMP_INTERVAL (5 * G_TIME_SPAN_MINUTE)
#define MAX_LINES 800
#define MAX_SCROLL_TIME 0.4 /* seconds */
@@ -66,7 +66,7 @@ typedef struct {
gboolean find_wrapped;
gboolean find_last_direction;
EmpathyContact *last_contact;
- time_t last_timestamp;
+ gint64 last_timestamp;
gboolean allow_scrolling;
guint notify_system_fonts_id;
GConfClient *gconf_client;
@@ -402,7 +402,7 @@ chat_text_view_maybe_trim_buffer (EmpathyChatTextView *view)
static void
chat_text_view_append_timestamp (EmpathyChatTextView *view,
- time_t timestamp,
+ gint64 timestamp,
gboolean show_date)
{
EmpathyChatTextViewPriv *priv = GET_PRIV (view);
@@ -414,17 +414,12 @@ chat_text_view_append_timestamp (EmpathyChatTextView *view,
/* Append date if needed */
if (show_date) {
- GDate *date;
- gchar buf[256];
-
- date = g_date_new ();
- g_date_set_time_t (date, timestamp);
/* Translators: timestamp displayed between conversations in
* chat windows (strftime format string) */
- g_date_strftime (buf, 256, _("%A %B %d %Y"), date);
- g_string_append (str, buf);
+ tmp = empathy_time_to_string_utc (timestamp, _("%A %B %d %Y"));
+ g_string_append (str, tmp);
g_string_append (str, ", ");
- g_date_free (date);
+ g_free (tmp);
}
/* Append time */
@@ -448,32 +443,32 @@ chat_text_view_append_timestamp (EmpathyChatTextView *view,
static void
chat_text_maybe_append_date_and_time (EmpathyChatTextView *view,
- time_t timestamp)
+ gint64 timestamp)
{
EmpathyChatTextViewPriv *priv = GET_PRIV (view);
- GDate *date, *last_date;
+ GDateTime *date, *last_date;
gboolean append_date = FALSE;
gboolean append_time = FALSE;
+ GTimeSpan delta;
/* Get the date from last message */
- last_date = g_date_new ();
- g_date_set_time_t (last_date, priv->last_timestamp);
+ last_date = g_date_time_new_from_unix_utc (priv->last_timestamp);
/* Get the date of the message we are appending */
- date = g_date_new ();
- g_date_set_time_t (date, timestamp);
+ date = g_date_time_new_from_unix_utc (timestamp);
+ delta = g_date_time_difference (last_date, date);
/* If last message was from another day we append date and time */
- if (g_date_compare (date, last_date) > 0) {
+ if (delta >= G_TIME_SPAN_DAY) {
append_date = TRUE;
append_time = TRUE;
}
- g_date_free (last_date);
- g_date_free (date);
+ g_date_time_unref (last_date);
+ g_date_time_unref (date);
/* If last message is 'old' append the time */
- if (timestamp - priv->last_timestamp >= TIMESTAMP_INTERVAL) {
+ if (delta >= TIMESTAMP_INTERVAL) {
append_time = TRUE;
}
@@ -732,7 +727,7 @@ chat_text_view_append_message (EmpathyChatView *view,
EmpathyChatTextView *text_view = EMPATHY_CHAT_TEXT_VIEW (view);
EmpathyChatTextViewPriv *priv = GET_PRIV (text_view);
gboolean bottom;
- time_t timestamp;
+ gint64 timestamp;
g_return_if_fail (EMPATHY_IS_CHAT_TEXT_VIEW (view));
g_return_if_fail (EMPATHY_IS_MESSAGE (msg));
@@ -1327,7 +1322,7 @@ empathy_chat_text_view_get_last_contact (EmpathyChatTextView *view)
return priv->last_contact;
}
-time_t
+gint64
empathy_chat_text_view_get_last_timestamp (EmpathyChatTextView *view)
{
EmpathyChatTextViewPriv *priv = GET_PRIV (view);
diff --git a/libempathy-gtk/empathy-chat-text-view.h b/libempathy-gtk/empathy-chat-text-view.h
index 7ee7ba8a2..12edbcc64 100644
--- a/libempathy-gtk/empathy-chat-text-view.h
+++ b/libempathy-gtk/empathy-chat-text-view.h
@@ -70,7 +70,7 @@ struct _EmpathyChatTextViewClass {
GType empathy_chat_text_view_get_type (void) G_GNUC_CONST;
EmpathyContact * empathy_chat_text_view_get_last_contact (EmpathyChatTextView *view);
-time_t empathy_chat_text_view_get_last_timestamp (EmpathyChatTextView *view);
+gint64 empathy_chat_text_view_get_last_timestamp (EmpathyChatTextView *view);
void empathy_chat_text_view_set_only_if_date (EmpathyChatTextView *view,
gboolean only_if_date);
void empathy_chat_text_view_append_body (EmpathyChatTextView *view,
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c
index e25c8ff6f..ee18be657 100644
--- a/libempathy-gtk/empathy-chat.c
+++ b/libempathy-gtk/empathy-chat.c
@@ -815,10 +815,35 @@ chat_command_me (EmpathyChat *chat,
GStrv strv)
{
EmpathyChatPriv *priv = GET_PRIV (chat);
- EmpathyMessage *message;
+ TpMessage *message;
+ TpChannel *channel;
+
+ channel = empathy_tp_chat_get_channel (priv->tp_chat);
+
+ /* Strictly speaking we don't depend yet on Messages so best to check that
+ * the channel is actually a TpTextChannel before casting it. */
+ if (TP_IS_TEXT_CHANNEL (channel) &&
+ !tp_text_channel_supports_message_type (TP_TEXT_CHANNEL (channel),
+ TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION)) {
+ /* Action message are not supported, 'simulate' the action */
+ EmpathyContact *self_contact;
+ gchar *tmp;
+
+ self_contact = empathy_tp_chat_get_self_contact (priv->tp_chat);
+ /* The TpChat can't be ready if it doesn't have the self contact */
+ g_assert (self_contact != NULL);
+
+ tmp = g_strdup_printf ("%s %s", empathy_contact_get_alias (self_contact),
+ strv[1]);
+ message = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+ tmp);
+ g_free (tmp);
+ }
+ else {
+ message = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION,
+ strv[1]);
+ }
- message = empathy_message_new (strv[1]);
- empathy_message_set_tptype (message, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION);
empathy_tp_chat_send (priv->tp_chat, message);
g_object_unref (message);
}
@@ -828,9 +853,10 @@ chat_command_say (EmpathyChat *chat,
GStrv strv)
{
EmpathyChatPriv *priv = GET_PRIV (chat);
- EmpathyMessage *message;
+ TpMessage *message;
- message = empathy_message_new (strv[1]);
+ message = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+ strv[1]);
empathy_tp_chat_send (priv->tp_chat, message);
g_object_unref (message);
}
@@ -979,7 +1005,7 @@ chat_send (EmpathyChat *chat,
const gchar *msg)
{
EmpathyChatPriv *priv;
- EmpathyMessage *message;
+ TpMessage *message;
guint i;
if (EMP_STR_EMPTY (msg)) {
@@ -1044,7 +1070,8 @@ chat_send (EmpathyChat *chat,
}
}
- message = empathy_message_new (msg);
+ message = tp_client_message_new_text (TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+ msg);
empathy_tp_chat_send (priv->tp_chat, message);
g_object_unref (message);
}
@@ -1198,9 +1225,14 @@ chat_send_error_cb (EmpathyTpChat *tp_chat,
break;
}
- str = g_strdup_printf (_("Error sending message '%s': %s"),
- message_body,
- error);
+ if (message_body != NULL) {
+ str = g_strdup_printf (_("Error sending message '%s': %s"),
+ message_body, error);
+ }
+ else {
+ str = g_strdup_printf (_("Error sending message: %s"), error);
+ }
+
empathy_chat_view_append_event (chat->view, str);
g_free (str);
}
diff --git a/libempathy-gtk/empathy-contact-blocking-dialog.ui b/libempathy-gtk/empathy-contact-blocking-dialog.ui
index b2ea89b81..dd17126d7 100644
--- a/libempathy-gtk/empathy-contact-blocking-dialog.ui
+++ b/libempathy-gtk/empathy-contact-blocking-dialog.ui
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
@@ -13,6 +13,7 @@
<object class="GtkVBox" id="contents">
<property name="visible">True</property>
<property name="border_width">6</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkHBox" id="account-hbox">
@@ -82,12 +83,11 @@
<property name="layout_style">start</property>
<child>
<object class="GtkButton" id="remove-button">
- <property name="label">gtk-remove</property>
+ <property name="label">Unblock</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -114,7 +114,7 @@
<object class="GtkEntry" id="add-contact-entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="invisible_char">●</property>
+ <property name="invisible_char">&#x25CF;</property>
</object>
<packing>
<property name="position">0</property>
@@ -142,8 +142,8 @@
</object>
<object class="GtkSizeGroup" id="sizegroup1">
<widgets>
- <widget name="add-button"/>
<widget name="remove-button"/>
+ <widget name="add-button"/>
</widgets>
</object>
</interface>
diff --git a/libempathy-gtk/empathy-contact-widget.c b/libempathy-gtk/empathy-contact-widget.c
index 61e04560e..93ab9d510 100644
--- a/libempathy-gtk/empathy-contact-widget.c
+++ b/libempathy-gtk/empathy-contact-widget.c
@@ -724,13 +724,11 @@ contact_widget_location_update (EmpathyContactWidget *information)
gchar *user_date;
gchar *text;
gint64 stamp;
- time_t time_;
gchar *tmp;
stamp = g_value_get_int64 (value);
- time_ = stamp;
- user_date = empathy_time_to_string_relative (time_);
+ user_date = empathy_time_to_string_relative (stamp);
tmp = g_strdup_printf ("<b>%s</b>", _("Location"));
/* translators: format is "Location, $date" */
@@ -783,7 +781,7 @@ contact_widget_location_update (EmpathyContactWidget *information)
}
else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT64)
{
- time_t time_;
+ gint64 time_;
time_ = g_value_get_int64 (value);
svalue = empathy_time_to_string_utc (time_, _("%B %e, %Y at %R UTC"));
diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c
index 90a9fc6db..12486195c 100644
--- a/libempathy-gtk/empathy-individual-view.c
+++ b/libempathy-gtk/empathy-individual-view.c
@@ -2229,8 +2229,8 @@ empathy_individual_view_get_selected_group (EmpathyIndividualView *view,
enum
{
REMOVE_DIALOG_RESPONSE_CANCEL = 0,
- REMOVE_DIALOG_RESPONSE_DELETE,
- REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK,
+ REMOVE_DIALOG_RESPONSE_REMOVE,
+ REMOVE_DIALOG_RESPONSE_REMOVE_AND_BLOCK,
};
static int
@@ -2260,17 +2260,17 @@ individual_view_remove_dialog_show (GtkWindow *parent,
/* gtk_dialog_add_button() doesn't allow us to pass a string with a
* mnemonic so we have to create the button manually. */
button = gtk_button_new_with_mnemonic (
- _("Delete and _Block"));
+ _("Remove and _Block"));
gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
- REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK);
+ REMOVE_DIALOG_RESPONSE_REMOVE_AND_BLOCK);
gtk_widget_show (button);
}
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, REMOVE_DIALOG_RESPONSE_CANCEL,
- GTK_STOCK_DELETE, REMOVE_DIALOG_RESPONSE_DELETE, NULL);
+ GTK_STOCK_REMOVE, REMOVE_DIALOG_RESPONSE_REMOVE, NULL);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", secondary_text);
@@ -2300,7 +2300,7 @@ individual_view_group_remove_activate_cb (GtkMenuItem *menuitem,
group);
parent = empathy_get_toplevel_window (GTK_WIDGET (view));
if (individual_view_remove_dialog_show (parent, _("Removing group"),
- text, FALSE, NULL) == REMOVE_DIALOG_RESPONSE_DELETE)
+ text, FALSE, NULL) == REMOVE_DIALOG_RESPONSE_REMOVE)
{
EmpathyIndividualManager *manager =
empathy_individual_manager_dup_singleton ();
@@ -2409,12 +2409,12 @@ got_avatar (GObject *source_object,
res = individual_view_remove_dialog_show (parent, _("Removing contact"),
text, can_block, avatar);
- if (res == REMOVE_DIALOG_RESPONSE_DELETE ||
- res == REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK)
+ if (res == REMOVE_DIALOG_RESPONSE_REMOVE ||
+ res == REMOVE_DIALOG_RESPONSE_REMOVE_AND_BLOCK)
{
gboolean abusive;
- if (res == REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK)
+ if (res == REMOVE_DIALOG_RESPONSE_REMOVE_AND_BLOCK)
{
if (!empathy_block_individual_dialog_show (parent, individual,
avatar, &abusive))
diff --git a/libempathy-gtk/empathy-individual-widget.c b/libempathy-gtk/empathy-individual-widget.c
index ed5e3be6f..b2020fc6c 100644
--- a/libempathy-gtk/empathy-individual-widget.c
+++ b/libempathy-gtk/empathy-individual-widget.c
@@ -588,13 +588,11 @@ location_update (EmpathyIndividualWidget *self)
gchar *user_date;
gchar *text;
gint64 stamp;
- time_t time_;
gchar *tmp;
stamp = g_value_get_int64 (value);
- time_ = stamp;
- user_date = empathy_time_to_string_relative (time_);
+ user_date = empathy_time_to_string_relative (stamp);
tmp = g_strdup_printf ("<b>%s</b>", _("Location"));
/* translators: format is "Location, $date" */
@@ -644,7 +642,7 @@ location_update (EmpathyIndividualWidget *self)
}
else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT64)
{
- time_t time_;
+ gint64 time_;
time_ = g_value_get_int64 (value);
svalue = empathy_time_to_string_utc (time_, _("%B %e, %Y at %R UTC"));
diff --git a/libempathy-gtk/empathy-location-manager.c b/libempathy-gtk/empathy-location-manager.c
index 1c09c358c..8f64e325f 100644
--- a/libempathy-gtk/empathy-location-manager.c
+++ b/libempathy-gtk/empathy-location-manager.c
@@ -39,6 +39,7 @@
#include "libempathy/empathy-gsettings.h"
#include "libempathy/empathy-location.h"
#include "libempathy/empathy-utils.h"
+#include "libempathy/empathy-time.h"
#define DEBUG_FLAG EMPATHY_DEBUG_LOCATION
#include "libempathy/empathy-debug.h"
@@ -322,16 +323,15 @@ static void
update_timestamp (EmpathyLocationManager *self)
{
EmpathyLocationManagerPriv *priv= GET_PRIV (self);
+ gint64 timestamp;
GValue *new_value;
- gint64 stamp64;
- time_t timestamp;
- timestamp = time (NULL);
- stamp64 = (gint64) timestamp;
- new_value = tp_g_value_slice_new_int64 (stamp64);
+ timestamp = empathy_time_get_current ();
+ new_value = tp_g_value_slice_new_int64 (timestamp);
g_hash_table_insert (priv->location, g_strdup (EMPATHY_LOCATION_TIMESTAMP),
new_value);
- DEBUG ("\t - Timestamp: %" G_GINT64_FORMAT, stamp64);
+
+ DEBUG ("\t - Timestamp: %" G_GINT64_FORMAT, timestamp);
}
static void
diff --git a/libempathy-gtk/empathy-log-window.c b/libempathy-gtk/empathy-log-window.c
index 8bb92b82e..f6b5edf16 100644
--- a/libempathy-gtk/empathy-log-window.c
+++ b/libempathy-gtk/empathy-log-window.c
@@ -786,37 +786,11 @@ log_window_chats_changed_cb (GtkTreeSelection *selection,
log_window_chats_get_messages (window, NULL);
}
-typedef struct
-{
- EmpathyLogWindow *window;
- TpAccount *account;
-} GetEntitiesCtx;
-
-static GetEntitiesCtx *
-get_entities_ctx_new (EmpathyLogWindow *window,
- TpAccount *account)
-{
- GetEntitiesCtx *ctx = g_slice_new (GetEntitiesCtx);
-
- /* EmpathyLogWindow isn't a proper GObject so we can't ref it */
- ctx->window = window;
- ctx->account = g_object_ref (account);
- return ctx;
-}
-
-static void
-get_entities_ctx_free (GetEntitiesCtx *ctx)
-{
- g_object_unref (ctx->account);
- g_slice_free (GetEntitiesCtx, ctx);
-}
-
static void
log_manager_got_entities_cb (GObject *manager,
GAsyncResult *result,
gpointer user_data)
{
- GetEntitiesCtx *ctx = user_data;
GList *entities;
GList *l;
GtkTreeView *view;
@@ -826,8 +800,7 @@ log_manager_got_entities_cb (GObject *manager,
GtkTreeIter iter;
GError *error = NULL;
gboolean select_account = FALSE;
-
- view = GTK_TREE_VIEW (ctx->window->treeview_chats);
+ TpAccount *account = user_data;
if (log_window == NULL)
goto out;
@@ -839,7 +812,7 @@ log_manager_got_entities_cb (GObject *manager,
goto out;
}
- view = GTK_TREE_VIEW (ctx->window->treeview_chats);
+ view = GTK_TREE_VIEW (log_window->treeview_chats);
model = gtk_tree_view_get_model (view);
selection = gtk_tree_view_get_selection (view);
store = GTK_LIST_STORE (model);
@@ -853,13 +826,13 @@ log_manager_got_entities_cb (GObject *manager,
gtk_list_store_set (store, &iter,
COL_CHAT_ICON, "empathy-available", /* FIXME */
COL_CHAT_NAME, tpl_entity_get_alias (entity),
- COL_CHAT_ACCOUNT, ctx->account,
+ COL_CHAT_ACCOUNT, account,
COL_CHAT_TARGET, entity,
-1);
- if (ctx->window->selected_account != NULL &&
- !tp_strdiff (tp_proxy_get_object_path (ctx->account),
- tp_proxy_get_object_path (ctx->window->selected_account)))
+ if (log_window->selected_account != NULL &&
+ !tp_strdiff (tp_proxy_get_object_path (account),
+ tp_proxy_get_object_path (log_window->selected_account)))
select_account = TRUE;
/* FIXME: Update COL_CHAT_ICON/NAME */
@@ -872,15 +845,15 @@ log_manager_got_entities_cb (GObject *manager,
/* Unblock signals */
g_signal_handlers_unblock_by_func (selection,
log_window_chats_changed_cb,
- ctx->window);
+ log_window);
/* We display the selected account if we populate the model with chats from
* this account. */
if (select_account)
- log_window_chats_set_selected (ctx->window);
+ log_window_chats_set_selected (log_window);
out:
- get_entities_ctx_free (ctx);
+ g_object_unref (account);
}
static void
@@ -893,7 +866,6 @@ log_window_chats_populate (EmpathyLogWindow *window)
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkListStore *store;
- GetEntitiesCtx *ctx;
account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser_chats);
account = empathy_account_chooser_dup_account (account_chooser);
@@ -915,10 +887,9 @@ log_window_chats_populate (EmpathyLogWindow *window)
gtk_list_store_clear (store);
- ctx = get_entities_ctx_new (window, account);
-
+ /* Pass the account reference to the callback */
tpl_log_manager_get_entities_async (window->log_manager, account,
- log_manager_got_entities_cb, ctx);
+ log_manager_got_entities_cb, account);
}
static void
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index b2f759e30..2569e7faf 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -59,7 +59,7 @@ typedef struct {
EmpathyAdiumData *data;
EmpathySmileyManager *smiley_manager;
EmpathyContact *last_contact;
- time_t last_timestamp;
+ gint64 last_timestamp;
gboolean last_is_backlog;
guint pages_loading;
GList *message_queue;
@@ -324,7 +324,7 @@ theme_adium_append_html (EmpathyThemeAdium *theme,
const gchar *contact_id,
const gchar *service_name,
const gchar *message_classes,
- time_t timestamp,
+ gint64 timestamp,
gboolean is_backlog)
{
GString *string;
@@ -442,7 +442,7 @@ theme_adium_append_message (EmpathyChatView *view,
const gchar *contact_id;
EmpathyAvatar *avatar;
const gchar *avatar_filename = NULL;
- time_t timestamp;
+ gint64 timestamp;
gchar *html = NULL;
gsize len = 0;
const gchar *func;
diff --git a/libempathy-gtk/empathy-theme-boxes.c b/libempathy-gtk/empathy-theme-boxes.c
index bf97f3f97..c0377b6ae 100644
--- a/libempathy-gtk/empathy-theme-boxes.c
+++ b/libempathy-gtk/empathy-theme-boxes.c
@@ -196,7 +196,7 @@ theme_boxes_maybe_append_header (EmpathyThemeBoxes *theme,
GtkTextChildAnchor *anchor;
GtkWidget *box;
gchar *str;
- time_t time_;
+ gint64 time_;
gchar *tmp;
GtkTextIter start;
gboolean color_set;
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index a9503e14a..dfe7c6fee 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -1688,19 +1688,18 @@ tp_caps_to_capabilities (TpCapabilities *caps)
TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO))
capabilities |= EMPATHY_CAPABILITIES_VIDEO;
}
- }
- else if (!tp_strdiff (chan_type,
- TPY_IFACE_CHANNEL_TYPE_CALL))
- {
- guint j;
if (tp_asv_get_boolean (fixed_prop,
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL))
+ TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL))
capabilities |= EMPATHY_CAPABILITIES_AUDIO;
-
if (tp_asv_get_boolean (fixed_prop,
- TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL))
+ TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL))
capabilities |= EMPATHY_CAPABILITIES_VIDEO;
+ }
+ else if (!tp_strdiff (chan_type,
+ TPY_IFACE_CHANNEL_TYPE_CALL))
+ {
+ guint j;
for (j = 0; allowed_prop[j] != NULL; j++)
{
@@ -1711,6 +1710,13 @@ tp_caps_to_capabilities (TpCapabilities *caps)
TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO))
capabilities |= EMPATHY_CAPABILITIES_VIDEO;
}
+
+ if (tp_asv_get_boolean (fixed_prop,
+ TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL))
+ capabilities |= EMPATHY_CAPABILITIES_AUDIO;
+ if (tp_asv_get_boolean (fixed_prop,
+ TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL))
+ capabilities |= EMPATHY_CAPABILITIES_VIDEO;
}
else if (!tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
{
diff --git a/libempathy/empathy-ft-handler.c b/libempathy/empathy-ft-handler.c
index 94b9cf3d4..26db91b07 100644
--- a/libempathy/empathy-ft-handler.c
+++ b/libempathy/empathy-ft-handler.c
@@ -144,7 +144,7 @@ typedef struct {
/* time and speed */
gdouble speed;
guint remaining_time;
- time_t last_update_time;
+ gint64 last_update_time;
gboolean is_completed;
} EmpathyFTHandlerPriv;
@@ -662,7 +662,7 @@ update_remaining_time_and_speed (EmpathyFTHandler *handler,
guint64 transferred_bytes)
{
EmpathyFTHandlerPriv *priv = GET_PRIV (handler);
- time_t elapsed_time, current_time;
+ gint64 elapsed_time, current_time;
guint64 transferred, last_transferred_bytes;
gdouble speed;
gint remaining_time;
diff --git a/libempathy/empathy-message.c b/libempathy/empathy-message.c
index 65ea2ae40..076a10053 100644
--- a/libempathy/empathy-message.c
+++ b/libempathy/empathy-message.c
@@ -44,7 +44,7 @@ typedef struct {
EmpathyContact *sender;
EmpathyContact *receiver;
gchar *body;
- time_t timestamp;
+ gint64 timestamp;
gboolean is_backlog;
guint id;
gboolean incoming;
@@ -93,44 +93,46 @@ empathy_message_class_init (EmpathyMessageClass *class)
TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_SENDER,
g_param_spec_object ("sender",
"Message Sender",
"The sender of the message",
EMPATHY_TYPE_CONTACT,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_RECEIVER,
g_param_spec_object ("receiver",
"Message Receiver",
"The receiver of the message",
EMPATHY_TYPE_CONTACT,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_BODY,
g_param_spec_string ("body",
"Message Body",
"The content of the message",
NULL,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_TIMESTAMP,
- g_param_spec_long ("timestamp",
+ g_param_spec_int64 ("timestamp",
"timestamp",
"timestamp",
- -1,
- G_MAXLONG,
- -1,
- G_PARAM_READWRITE));
+ G_MININT64, G_MAXINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_IS_BACKLOG,
g_param_spec_boolean ("is-backlog",
"History message",
"If the message belongs to history",
FALSE,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
@@ -139,7 +141,8 @@ empathy_message_class_init (EmpathyMessageClass *class)
"Incoming",
"If this is an incoming (as opposed to sent) message",
FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_FLAGS,
@@ -147,7 +150,8 @@ empathy_message_class_init (EmpathyMessageClass *class)
"Flags",
"The TpChannelTextMessageFlags of this message",
0, G_MAXUINT, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
@@ -205,9 +209,18 @@ message_get_property (GObject *object,
case PROP_BODY:
g_value_set_string (value, priv->body);
break;
+ case PROP_TIMESTAMP:
+ g_value_set_int64 (value, priv->timestamp);
+ break;
+ case PROP_IS_BACKLOG:
+ g_value_set_boolean (value, priv->is_backlog);
+ break;
case PROP_INCOMING:
g_value_set_boolean (value, priv->incoming);
break;
+ case PROP_FLAGS:
+ g_value_set_uint (value, priv->flags);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -226,8 +239,7 @@ message_set_property (GObject *object,
switch (param_id) {
case PROP_TYPE:
- empathy_message_set_tptype (EMPATHY_MESSAGE (object),
- g_value_get_uint (value));
+ priv->type = g_value_get_uint (value);
break;
case PROP_SENDER:
empathy_message_set_sender (EMPATHY_MESSAGE (object),
@@ -238,12 +250,23 @@ message_set_property (GObject *object,
EMPATHY_CONTACT (g_value_get_object (value)));
break;
case PROP_BODY:
- empathy_message_set_body (EMPATHY_MESSAGE (object),
- g_value_get_string (value));
+ g_assert (priv->body == NULL); /* construct only */
+ priv->body = g_value_dup_string (value);
+ break;
+ case PROP_TIMESTAMP:
+ priv->timestamp = g_value_get_int64 (value);
+ if (priv->timestamp <= 0)
+ priv->timestamp = empathy_time_get_current ();
+ break;
+ case PROP_IS_BACKLOG:
+ priv->is_backlog = g_value_get_boolean (value);
break;
case PROP_INCOMING:
priv->incoming = g_value_get_boolean (value);
break;
+ case PROP_FLAGS:
+ priv->flags = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -251,14 +274,6 @@ message_set_property (GObject *object,
}
EmpathyMessage *
-empathy_message_new (const gchar *body)
-{
- return g_object_new (EMPATHY_TYPE_MESSAGE,
- "body", body,
- NULL);
-}
-
-EmpathyMessage *
empathy_message_from_tpl_log_event (TplEvent *logevent)
{
EmpathyMessage *retval = NULL;
@@ -303,7 +318,13 @@ empathy_message_from_tpl_log_event (TplEvent *logevent)
receiver = tpl_event_get_receiver (logevent);
sender = tpl_event_get_sender (logevent);
- retval = empathy_message_new (body);
+ retval = g_object_new (EMPATHY_TYPE_MESSAGE,
+ "type", tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent)),
+ "body", body,
+ "is-backlog", TRUE,
+ "timestamp", tpl_event_get_timestamp (logevent),
+ NULL);
+
if (receiver != NULL) {
contact = empathy_contact_from_tpl_contact (account, receiver);
empathy_message_set_receiver (retval, contact);
@@ -316,12 +337,6 @@ empathy_message_from_tpl_log_event (TplEvent *logevent)
g_object_unref (contact);
}
- empathy_message_set_timestamp (retval,
- tpl_event_get_timestamp (logevent));
- empathy_message_set_tptype (retval,
- tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent)));
- empathy_message_set_is_backlog (retval, TRUE);
-
g_free (body);
return retval;
@@ -340,21 +355,6 @@ empathy_message_get_tptype (EmpathyMessage *message)
return priv->type;
}
-void
-empathy_message_set_tptype (EmpathyMessage *message,
- TpChannelTextMessageType type)
-{
- EmpathyMessagePriv *priv;
-
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-
- priv = GET_PRIV (message);
-
- priv->type = type;
-
- g_object_notify (G_OBJECT (message), "type");
-}
-
EmpathyContact *
empathy_message_get_sender (EmpathyMessage *message)
{
@@ -433,26 +433,7 @@ empathy_message_get_body (EmpathyMessage *message)
return priv->body;
}
-void
-empathy_message_set_body (EmpathyMessage *message,
- const gchar *body)
-{
- EmpathyMessagePriv *priv = GET_PRIV (message);
-
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-
- g_free (priv->body);
-
- if (body) {
- priv->body = g_strdup (body);
- } else {
- priv->body = NULL;
- }
-
- g_object_notify (G_OBJECT (message), "body");
-}
-
-time_t
+gint64
empathy_message_get_timestamp (EmpathyMessage *message)
{
EmpathyMessagePriv *priv;
@@ -464,26 +445,6 @@ empathy_message_get_timestamp (EmpathyMessage *message)
return priv->timestamp;
}
-void
-empathy_message_set_timestamp (EmpathyMessage *message,
- time_t timestamp)
-{
- EmpathyMessagePriv *priv;
-
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
- g_return_if_fail (timestamp >= -1);
-
- priv = GET_PRIV (message);
-
- if (timestamp <= 0) {
- priv->timestamp = empathy_time_get_current ();
- } else {
- priv->timestamp = timestamp;
- }
-
- g_object_notify (G_OBJECT (message), "timestamp");
-}
-
gboolean
empathy_message_is_backlog (EmpathyMessage *message)
{
@@ -496,21 +457,6 @@ empathy_message_is_backlog (EmpathyMessage *message)
return priv->is_backlog;
}
-void
-empathy_message_set_is_backlog (EmpathyMessage *message,
- gboolean is_backlog)
-{
- EmpathyMessagePriv *priv;
-
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-
- priv = GET_PRIV (message);
-
- priv->is_backlog = is_backlog;
-
- g_object_notify (G_OBJECT (message), "is-backlog");
-}
-
#define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
gboolean
empathy_message_should_highlight (EmpathyMessage *message)
@@ -627,28 +573,6 @@ empathy_message_get_id (EmpathyMessage *message)
return priv->id;
}
-void
-empathy_message_set_id (EmpathyMessage *message, guint id)
-{
- EmpathyMessagePriv *priv = GET_PRIV (message);
-
- priv->id = id;
-}
-
-void
-empathy_message_set_incoming (EmpathyMessage *message, gboolean incoming)
-{
- EmpathyMessagePriv *priv;
-
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-
- priv = GET_PRIV (message);
-
- priv->incoming = incoming;
-
- g_object_notify (G_OBJECT (message), "incoming");
-}
-
gboolean
empathy_message_is_incoming (EmpathyMessage *message)
{
@@ -689,17 +613,38 @@ empathy_message_get_flags (EmpathyMessage *self)
return priv->flags;
}
-void
-empathy_message_set_flags (EmpathyMessage *self,
- TpChannelTextMessageFlags flags)
+EmpathyMessage *
+empathy_message_new_from_tp_message (TpMessage *tp_msg,
+ gboolean incoming)
{
+ EmpathyMessage *message;
EmpathyMessagePriv *priv;
+ gchar *body;
+ TpChannelTextMessageFlags flags;
+ guint id;
+
+ g_return_val_if_fail (TP_IS_MESSAGE (tp_msg), NULL);
- g_return_if_fail (EMPATHY_IS_MESSAGE (self));
+ body = tp_message_to_text (tp_msg, &flags);
- priv = GET_PRIV (self);
+ message = g_object_new (EMPATHY_TYPE_MESSAGE,
+ "body", body,
+ "type", tp_message_get_message_type (tp_msg),
+ "timestamp", tp_message_get_received_timestamp (tp_msg),
+ "flags", flags,
+ "is-backlog", flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK,
+ "incoming", incoming,
+ NULL);
- priv->flags = flags;
+ priv = GET_PRIV (message);
+
+ /* FIXME: this is pretty low level, ideally we shouldn't have to use the
+ * ID directly but we don't use TpTextChannel's ack API everywhere yet. */
+ id = tp_asv_get_uint32 (tp_message_peek (tp_msg, 0),
+ "pending-message-id", NULL);
- g_object_notify (G_OBJECT (self), "flags");
+ priv->id = id;
+
+ g_free (body);
+ return message;
}
diff --git a/libempathy/empathy-message.h b/libempathy/empathy-message.h
index 1db0eff60..7508cb08e 100644
--- a/libempathy/empathy-message.h
+++ b/libempathy/empathy-message.h
@@ -26,6 +26,7 @@
#define __EMPATHY_MESSAGE_H__
#include <glib-object.h>
+#include <telepathy-glib/message.h>
#include <telepathy-logger/event.h>
#include "empathy-contact.h"
@@ -53,11 +54,12 @@ struct _EmpathyMessageClass {
};
GType empathy_message_get_type (void) G_GNUC_CONST;
-EmpathyMessage * empathy_message_new (const gchar *body);
+
EmpathyMessage * empathy_message_from_tpl_log_event (TplEvent *logevent);
+EmpathyMessage * empathy_message_new_from_tp_message (TpMessage *tp_msg,
+ gboolean incoming);
+
TpChannelTextMessageType empathy_message_get_tptype (EmpathyMessage *message);
-void empathy_message_set_tptype (EmpathyMessage *message,
- TpChannelTextMessageType type);
EmpathyContact * empathy_message_get_sender (EmpathyMessage *message);
void empathy_message_set_sender (EmpathyMessage *message,
EmpathyContact *contact);
@@ -65,30 +67,19 @@ EmpathyContact * empathy_message_get_receiver (EmpathyMessage
void empathy_message_set_receiver (EmpathyMessage *message,
EmpathyContact *contact);
const gchar * empathy_message_get_body (EmpathyMessage *message);
-void empathy_message_set_body (EmpathyMessage *message,
- const gchar *body);
-time_t empathy_message_get_timestamp (EmpathyMessage *message);
-void empathy_message_set_timestamp (EmpathyMessage *message,
- time_t timestamp);
+gint64 empathy_message_get_timestamp (EmpathyMessage *message);
gboolean empathy_message_is_backlog (EmpathyMessage *message);
-void empathy_message_set_is_backlog (EmpathyMessage *message,
- gboolean is_backlog);
gboolean empathy_message_is_incoming (EmpathyMessage *message);
-void empathy_message_set_incoming (EmpathyMessage *message,
- gboolean incoming);
gboolean empathy_message_should_highlight (EmpathyMessage *message);
TpChannelTextMessageType empathy_message_type_from_str (const gchar *type_str);
const gchar * empathy_message_type_to_str (TpChannelTextMessageType type);
guint empathy_message_get_id (EmpathyMessage *message);
-void empathy_message_set_id (EmpathyMessage *message, guint id);
gboolean empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2);
TpChannelTextMessageFlags empathy_message_get_flags (EmpathyMessage *message);
-void empathy_message_set_flags (EmpathyMessage *message,
- TpChannelTextMessageFlags flags);
G_END_DECLS
diff --git a/libempathy/empathy-time.c b/libempathy/empathy-time.c
index 13e17d152..f33152d97 100644
--- a/libempathy/empathy-time.c
+++ b/libempathy/empathy-time.c
@@ -31,139 +31,107 @@
/* Note: EmpathyTime is always in UTC. */
-time_t
+gint64
empathy_time_get_current (void)
{
- return time (NULL);
-}
-
-time_t
-empathy_time_get_local_time (struct tm *tm)
-{
- const gchar *tz;
- time_t t;
-
- tz = g_getenv ("TZ");
- g_setenv ("TZ", "", TRUE);
-
- tzset ();
-
- t = mktime (tm);
+ GDateTime *now;
+ gint64 result;
- if (tz) {
- g_setenv ("TZ", tz, TRUE);
- } else {
- g_unsetenv ("TZ");
- }
-
- tzset ();
+ now = g_date_time_new_now_utc ();
+ result = g_date_time_to_unix (now);
+ g_date_time_unref (now);
- return t;
-}
-
-/* The format is: "20021209T23:51:30" and is in UTC. 0 is returned on
- * failure. The alternative format "20021209" is also accepted.
- */
-time_t
-empathy_time_parse (const gchar *str)
-{
- struct tm tm;
- gint year, month;
- gint n_parsed;
-
- memset (&tm, 0, sizeof (struct tm));
-
- n_parsed = sscanf (str, "%4d%2d%2dT%2d:%2d:%2d",
- &year, &month, &tm.tm_mday, &tm.tm_hour,
- &tm.tm_min, &tm.tm_sec);
- if (n_parsed != 3 && n_parsed != 6) {
- return 0;
- }
-
- tm.tm_year = year - 1900;
- tm.tm_mon = month - 1;
- tm.tm_isdst = -1;
-
- return empathy_time_get_local_time (&tm);
+ return result;
}
/* Converts the UTC timestamp to a string, also in UTC. Returns NULL on failure. */
gchar *
-empathy_time_to_string_utc (time_t t,
+empathy_time_to_string_utc (gint64 t,
const gchar *format)
{
- gchar stamp[128];
- struct tm *tm;
+ GDateTime *d;
+ char *result;
g_return_val_if_fail (format != NULL, NULL);
- tm = gmtime (&t);
- if (strftime (stamp, sizeof (stamp), format, tm) == 0) {
- return NULL;
- }
+ d = g_date_time_new_from_unix_utc (t);
+ result = g_date_time_format (d, format);
+ g_date_time_unref (d);
- return g_strdup (stamp);
+ return result;
}
/* Converts the UTC timestamp to a string, in local time. Returns NULL on failure. */
gchar *
-empathy_time_to_string_local (time_t t,
+empathy_time_to_string_local (gint64 t,
const gchar *format)
{
- gchar stamp[128];
- struct tm *tm;
+ GDateTime *d, *local;
+ gchar *result;
g_return_val_if_fail (format != NULL, NULL);
- tm = localtime (&t);
- if (strftime (stamp, sizeof (stamp), format, tm) == 0) {
- return NULL;
- }
+ d = g_date_time_new_from_unix_utc (t);
+ local = g_date_time_to_local (d);
+ g_date_time_unref (d);
+
+ result = g_date_time_format (local, format);
+ g_date_time_unref (local);
- return g_strdup (stamp);
+ return result;
}
gchar *
-empathy_time_to_string_relative (time_t then)
+empathy_time_to_string_relative (gint64 t)
{
- time_t now;
+ GDateTime *now, *then;
gint seconds;
+ GTimeSpan delta;
+ gchar *result;
+
+ now = g_date_time_new_now_utc ();
+ then = g_date_time_new_from_unix_utc (t);
- now = time (NULL);
- seconds = now - then;
+ delta = g_date_time_difference (now, then);
+ seconds = delta / G_TIME_SPAN_SECOND;
if (seconds > 0) {
if (seconds < 60) {
- return g_strdup_printf (ngettext ("%d second ago",
+ result = g_strdup_printf (ngettext ("%d second ago",
"%d seconds ago", seconds), seconds);
}
else if (seconds < (60 * 60)) {
seconds /= 60;
- return g_strdup_printf (ngettext ("%d minute ago",
+ result = g_strdup_printf (ngettext ("%d minute ago",
"%d minutes ago", seconds), seconds);
}
else if (seconds < (60 * 60 * 24)) {
seconds /= 60 * 60;
- return g_strdup_printf (ngettext ("%d hour ago",
+ result = g_strdup_printf (ngettext ("%d hour ago",
"%d hours ago", seconds), seconds);
}
else if (seconds < (60 * 60 * 24 * 7)) {
seconds /= 60 * 60 * 24;
- return g_strdup_printf (ngettext ("%d day ago",
+ result = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", seconds), seconds);
}
else if (seconds < (60 * 60 * 24 * 30)) {
seconds /= 60 * 60 * 24 * 7;
- return g_strdup_printf (ngettext ("%d week ago",
+ result = g_strdup_printf (ngettext ("%d week ago",
"%d weeks ago", seconds), seconds);
}
else {
seconds /= 60 * 60 * 24 * 30;
- return g_strdup_printf (ngettext ("%d month ago",
+ result = g_strdup_printf (ngettext ("%d month ago",
"%d months ago", seconds), seconds);
}
}
else {
- return g_strdup (_("in the future"));
+ result = g_strdup (_("in the future"));
}
+
+ g_date_time_unref (now);
+ g_date_time_unref (then);
+
+ return result;
}
diff --git a/libempathy/empathy-time.h b/libempathy/empathy-time.h
index 65e0127c7..7fac48221 100644
--- a/libempathy/empathy-time.h
+++ b/libempathy/empathy-time.h
@@ -39,14 +39,12 @@ G_BEGIN_DECLS
#define EMPATHY_DATE_FORMAT_DISPLAY_SHORT _("%a %d %b %Y")
#define EMPATHY_TIME_DATE_FORMAT_DISPLAY_SHORT _("%a %d %b %Y, %H:%M")
-time_t empathy_time_get_current (void);
-time_t empathy_time_get_local_time (struct tm *tm);
-time_t empathy_time_parse (const gchar *str);
-gchar *empathy_time_to_string_utc (time_t t,
+gint64 empathy_time_get_current (void);
+gchar *empathy_time_to_string_utc (gint64 t,
const gchar *format);
-gchar *empathy_time_to_string_local (time_t t,
+gchar *empathy_time_to_string_local (gint64 t,
const gchar *format);
-gchar *empathy_time_to_string_relative (time_t t);
+gchar *empathy_time_to_string_relative (gint64 t);
G_END_DECLS
diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c
index da3ac663a..e829d6e6b 100644
--- a/libempathy/empathy-tp-chat.c
+++ b/libempathy/empathy-tp-chat.c
@@ -47,7 +47,6 @@ typedef struct {
EmpathyContact *remote_contact;
GList *members;
TpChannel *channel;
- gboolean listing_pending_messages;
/* Queue of messages not signalled yet */
GQueue *messages_queue;
/* Queue of messages signalled but not acked yet */
@@ -283,149 +282,176 @@ tp_chat_got_sender_cb (TpConnection *connection,
static void
tp_chat_build_message (EmpathyTpChat *chat,
- gboolean incoming,
- guint id,
- guint type,
- guint timestamp,
- guint from_handle,
- const gchar *message_body,
- TpChannelTextMessageFlags flags)
+ TpMessage *msg,
+ gboolean incoming)
{
EmpathyTpChatPriv *priv;
EmpathyMessage *message;
+ TpContact *sender;
priv = GET_PRIV (chat);
- message = empathy_message_new (message_body);
- empathy_message_set_tptype (message, type);
+ message = empathy_message_new_from_tp_message (msg, incoming);
+ /* FIXME: this is actually a lie for incoming messages. */
empathy_message_set_receiver (message, priv->user);
- empathy_message_set_timestamp (message, timestamp);
- empathy_message_set_id (message, id);
- empathy_message_set_incoming (message, incoming);
- empathy_message_set_flags (message, flags);
-
- if (flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_SCROLLBACK)
- empathy_message_set_is_backlog (message, TRUE);
g_queue_push_tail (priv->messages_queue, message);
- if (from_handle == 0) {
+ sender = tp_signalled_message_get_sender (msg);
+ g_assert (sender != NULL);
+
+ if (tp_contact_get_handle (sender) == 0) {
empathy_message_set_sender (message, priv->user);
tp_chat_emit_queued_messages (chat);
} else {
empathy_tp_contact_factory_get_from_handle (priv->connection,
- from_handle,
+ tp_contact_get_handle (sender),
tp_chat_got_sender_cb,
message, NULL, G_OBJECT (chat));
}
}
static void
-tp_chat_received_cb (TpChannel *channel,
- guint message_id,
- guint timestamp,
- guint from_handle,
- guint message_type,
- guint message_flags,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat_)
-{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
+handle_delivery_report (EmpathyTpChat *self,
+ TpMessage *message)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ TpDeliveryStatus delivery_status;
+ const GHashTable *header;
+ TpChannelTextSendError delivery_error;
+ gboolean valid;
+ GPtrArray *echo;
+ const gchar *message_body = NULL;
+
+ header = tp_message_peek (message, 0);
+ if (header == NULL)
+ goto out;
- if (priv->channel == NULL)
- return;
+ delivery_status = tp_asv_get_uint32 (header, "delivery-status", &valid);
+ if (!valid || delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED)
+ goto out;
+
+ delivery_error = tp_asv_get_uint32 (header, "delivery-error", &valid);
+ if (!valid)
+ delivery_error = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
+
+ /* TODO: ideally we should use tp-glib API giving us the echoed message as a
+ * TpMessage. (fdo #35884) */
+ echo = tp_asv_get_boxed (header, "delivery-echo",
+ TP_ARRAY_TYPE_MESSAGE_PART_LIST);
+ if (echo != NULL && echo->len >= 1) {
+ const GHashTable *echo_body;
+
+ echo_body = g_ptr_array_index (echo, 1);
+ if (echo_body != NULL)
+ message_body = tp_asv_get_string (echo_body, "content");
+ }
+
+ g_signal_emit (self, signals[SEND_ERROR], 0, message_body, delivery_error);
+
+out:
+ tp_text_channel_ack_message_async (TP_TEXT_CHANNEL (priv->channel),
+ message, NULL, NULL);
+}
+
+static void
+handle_incoming_message (EmpathyTpChat *self,
+ TpMessage *message,
+ gboolean pending)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ gchar *message_body;
- if (priv->listing_pending_messages) {
+ if (tp_message_is_delivery_report (message)) {
+ handle_delivery_report (self, message);
return;
}
- DEBUG ("Message received from channel %s: %s",
- tp_proxy_get_object_path (channel), message_body);
+ message_body = tp_message_to_text (message, NULL);
- if (message_flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT &&
- !tp_strdiff (message_body, "")) {
- GArray *ids;
+ DEBUG ("Message %s (channel %s): %s",
+ pending ? "pending" : "received",
+ tp_proxy_get_object_path (priv->channel), message_body);
+ if (message_body == NULL) {
DEBUG ("Empty message with NonTextContent, ignoring and acking.");
- ids = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
- g_array_append_val (ids, message_id);
- acknowledge_messages (chat, ids);
- g_array_free (ids, TRUE);
-
+ tp_text_channel_ack_message_async (TP_TEXT_CHANNEL (priv->channel),
+ message, NULL, NULL);
return;
}
- tp_chat_build_message (chat,
- TRUE,
- message_id,
- message_type,
- timestamp,
- from_handle,
- message_body,
- message_flags);
+ tp_chat_build_message (self, message, TRUE);
+
+ g_free (message_body);
}
static void
-tp_chat_sent_cb (TpChannel *channel,
- guint timestamp,
- guint message_type,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat_)
-{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
+message_received_cb (TpTextChannel *channel,
+ TpMessage *message,
+ EmpathyTpChat *chat)
+{
+ handle_incoming_message (chat, message, FALSE);
+}
- if (priv->channel == NULL)
- return;
+static void
+message_sent_cb (TpTextChannel *channel,
+ TpMessage *message,
+ TpMessageSendingFlags flags,
+ gchar *token,
+ EmpathyTpChat *chat)
+{
+ gchar *message_body;
+
+ message_body = tp_message_to_text (message, NULL);
DEBUG ("Message sent: %s", message_body);
- tp_chat_build_message (chat,
- FALSE,
- 0,
- message_type,
- timestamp,
- 0,
- message_body,
- 0);
+ tp_chat_build_message (chat, message, FALSE);
+
+ g_free (message_body);
}
-static void
-tp_chat_send_error_cb (TpChannel *channel,
- guint error_code,
- guint timestamp,
- guint message_type,
- const gchar *message_body,
- gpointer user_data,
- GObject *chat)
+static TpChannelTextSendError
+error_to_text_send_error (GError *error)
{
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
-
- if (priv->channel == NULL)
- return;
+ if (error->domain != TP_ERRORS)
+ return TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
- DEBUG ("Error sending '%s' (%d)", message_body, error_code);
+ switch (error->code) {
+ case TP_ERROR_OFFLINE:
+ return TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE;
+ case TP_ERROR_INVALID_HANDLE:
+ return TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT;
+ case TP_ERROR_PERMISSION_DENIED:
+ return TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED;
+ case TP_ERROR_NOT_IMPLEMENTED:
+ return TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED;
+ }
- g_signal_emit (chat, signals[SEND_ERROR], 0, message_body, error_code);
+ return TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
}
static void
-tp_chat_send_cb (TpChannel *proxy,
- const GError *error,
- gpointer user_data,
- GObject *chat)
+message_send_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
- EmpathyMessage *message = EMPATHY_MESSAGE (user_data);
+ EmpathyTpChat *chat = user_data;
+ TpTextChannel *channel = (TpTextChannel *) source;
+ GError *error = NULL;
- if (error) {
+ if (!tp_text_channel_send_message_finish (channel, result, NULL, &error)) {
DEBUG ("Error: %s", error->message);
+
+ /* FIXME: we should use the body of the message as first argument of the
+ * signal but can't easily get it as we just get a user_data pointer. Once
+ * we'll have rebased EmpathyTpChat on top of TpTextChannel we'll be able
+ * to use the user_data pointer to pass the message and fix this. */
g_signal_emit (chat, signals[SEND_ERROR], 0,
- empathy_message_get_body (message),
- TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN);
+ NULL, error_to_text_send_error (error));
+
+ g_error_free (error);
}
}
@@ -460,86 +486,33 @@ static void
tp_chat_state_changed_cb (TpChannel *channel,
TpHandle handle,
TpChannelChatState state,
- gpointer user_data,
- GObject *chat)
+ EmpathyTpChat *chat)
{
EmpathyTpChatPriv *priv = GET_PRIV (chat);
empathy_tp_contact_factory_get_from_handle (priv->connection, handle,
tp_chat_state_changed_got_contact_cb, GUINT_TO_POINTER (state),
- NULL, chat);
+ NULL, G_OBJECT (chat));
}
static void
-tp_chat_list_pending_messages_cb (TpChannel *channel,
- const GPtrArray *messages_list,
- const GError *error,
- gpointer user_data,
- GObject *chat_)
+list_pending_messages (EmpathyTpChat *self)
{
- EmpathyTpChat *chat = EMPATHY_TP_CHAT (chat_);
- EmpathyTpChatPriv *priv = GET_PRIV (chat);
- guint i;
- GArray *empty_non_text_content_ids = NULL;
-
- priv->listing_pending_messages = FALSE;
-
- if (priv->channel == NULL)
- return;
-
- if (error) {
- DEBUG ("Error listing pending messages: %s", error->message);
- return;
- }
-
- for (i = 0; i < messages_list->len; i++) {
- GValueArray *message_struct;
- const gchar *message_body;
- guint message_id;
- guint timestamp;
- guint from_handle;
- guint message_type;
- guint message_flags;
-
- message_struct = g_ptr_array_index (messages_list, i);
-
- message_id = g_value_get_uint (g_value_array_get_nth (message_struct, 0));
- timestamp = g_value_get_uint (g_value_array_get_nth (message_struct, 1));
- from_handle = g_value_get_uint (g_value_array_get_nth (message_struct, 2));
- message_type = g_value_get_uint (g_value_array_get_nth (message_struct, 3));
- message_flags = g_value_get_uint (g_value_array_get_nth (message_struct, 4));
- message_body = g_value_get_string (g_value_array_get_nth (message_struct, 5));
-
- DEBUG ("Message pending: %s", message_body);
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+ GList *messages, *l;
- if (message_flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT &&
- !tp_strdiff (message_body, "")) {
- DEBUG ("Empty message with NonTextContent, ignoring and acking.");
+ g_assert (priv->channel != NULL);
- if (empty_non_text_content_ids == NULL) {
- empty_non_text_content_ids = g_array_new (FALSE, FALSE, sizeof (guint));
- }
+ messages = tp_text_channel_get_pending_messages (
+ TP_TEXT_CHANNEL (priv->channel));
- g_array_append_val (empty_non_text_content_ids, message_id);
- continue;
- }
+ for (l = messages; l != NULL; l = g_list_next (l)) {
+ TpMessage *message = l->data;
- tp_chat_build_message (chat,
- TRUE,
- message_id,
- message_type,
- timestamp,
- from_handle,
- message_body,
- message_flags);
+ handle_incoming_message (self, message, FALSE);
}
- if (empty_non_text_content_ids != NULL) {
- acknowledge_messages (chat, empty_non_text_content_ids);
- g_array_free (empty_non_text_content_ids, TRUE);
- }
-
- check_ready (chat);
+ g_list_free (messages);
}
static void
@@ -867,32 +840,22 @@ check_almost_ready (EmpathyTpChat *chat)
priv->remote_contact == NULL)
return;
- tp_cli_channel_type_text_connect_to_received (priv->channel,
- tp_chat_received_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- priv->listing_pending_messages = TRUE;
-
- /* TpChat will be ready once ListPendingMessages returned and all the messages
- * have been added to the pending messages queue. */
- tp_cli_channel_type_text_call_list_pending_messages (priv->channel, -1,
- FALSE,
- tp_chat_list_pending_messages_cb,
- NULL, NULL,
- G_OBJECT (chat));
-
- tp_cli_channel_type_text_connect_to_sent (priv->channel,
- tp_chat_sent_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_type_text_connect_to_send_error (priv->channel,
- tp_chat_send_error_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
- tp_cli_channel_interface_chat_state_connect_to_chat_state_changed (priv->channel,
- tp_chat_state_changed_cb,
- NULL, NULL,
- G_OBJECT (chat), NULL);
+ /* We use the default factory so this feature should have been prepared */
+ g_assert (tp_proxy_is_prepared (priv->channel,
+ TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES));
+
+ tp_g_signal_connect_object (priv->channel, "message-received",
+ G_CALLBACK (message_received_cb), chat, 0);
+
+ list_pending_messages (chat);
+
+ tp_g_signal_connect_object (priv->channel, "message-sent",
+ G_CALLBACK (message_sent_cb), chat, 0);
+
+ tp_g_signal_connect_object (priv->channel, "chat-state-changed",
+ G_CALLBACK (tp_chat_state_changed_cb), chat, 0);
+
+ check_ready (chat);
}
static void
@@ -1618,7 +1581,7 @@ empathy_tp_chat_new (TpAccount *account,
TpChannel *channel)
{
g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
- g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
+ g_return_val_if_fail (TP_IS_TEXT_CHANNEL (channel), NULL);
return g_object_new (EMPATHY_TYPE_TP_CHAT,
"account", account,
@@ -1707,27 +1670,23 @@ empathy_tp_chat_is_ready (EmpathyTpChat *chat)
void
empathy_tp_chat_send (EmpathyTpChat *chat,
- EmpathyMessage *message)
+ TpMessage *message)
{
EmpathyTpChatPriv *priv = GET_PRIV (chat);
- const gchar *message_body;
- TpChannelTextMessageType message_type;
+ gchar *message_body;
g_return_if_fail (EMPATHY_IS_TP_CHAT (chat));
- g_return_if_fail (EMPATHY_IS_MESSAGE (message));
+ g_return_if_fail (TP_IS_CLIENT_MESSAGE (message));
g_return_if_fail (priv->ready);
- message_body = empathy_message_get_body (message);
- message_type = empathy_message_get_tptype (message);
+ message_body = tp_message_to_text (message, NULL);
DEBUG ("Sending message: %s", message_body);
- tp_cli_channel_type_text_call_send (priv->channel, -1,
- message_type,
- message_body,
- tp_chat_send_cb,
- g_object_ref (message),
- (GDestroyNotify) g_object_unref,
- G_OBJECT (chat));
+
+ tp_text_channel_send_message_async (TP_TEXT_CHANNEL (priv->channel),
+ message, 0, message_send_cb, chat);
+
+ g_free (message_body);
}
void
@@ -2052,3 +2011,13 @@ empathy_tp_chat_is_sms_channel (EmpathyTpChat *self)
return priv->sms_channel;
}
+
+EmpathyContact *
+empathy_tp_chat_get_self_contact (EmpathyTpChat *self)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+
+ g_return_val_if_fail (EMPATHY_IS_TP_CHAT (self), NULL);
+
+ return priv->user;
+}
diff --git a/libempathy/empathy-tp-chat.h b/libempathy/empathy-tp-chat.h
index a71c81c7e..d72c30e06 100644
--- a/libempathy/empathy-tp-chat.h
+++ b/libempathy/empathy-tp-chat.h
@@ -64,12 +64,13 @@ EmpathyTpChat *empathy_tp_chat_new (TpAccount *account,
TpChannel *channel);
const gchar * empathy_tp_chat_get_id (EmpathyTpChat *chat);
EmpathyContact *empathy_tp_chat_get_remote_contact (EmpathyTpChat *chat);
+EmpathyContact *empathy_tp_chat_get_self_contact (EmpathyTpChat *chat);
TpChannel * empathy_tp_chat_get_channel (EmpathyTpChat *chat);
TpAccount * empathy_tp_chat_get_account (EmpathyTpChat *chat);
TpConnection * empathy_tp_chat_get_connection (EmpathyTpChat *chat);
gboolean empathy_tp_chat_is_ready (EmpathyTpChat *chat);
void empathy_tp_chat_send (EmpathyTpChat *chat,
- EmpathyMessage *message);
+ TpMessage *message);
void empathy_tp_chat_set_state (EmpathyTpChat *chat,
TpChannelChatState state);
void empathy_tp_chat_set_property (EmpathyTpChat *chat,
diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c
index d69b2153a..3bb2dd49c 100644
--- a/libempathy/empathy-tp-file.c
+++ b/libempathy/empathy-tp-file.c
@@ -79,7 +79,7 @@ struct _EmpathyTpFilePrivate {
/* transfer properties */
gboolean incoming;
- time_t start_time;
+ gint64 start_time;
GArray *socket_address;
guint port;
guint64 offset;
diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c
index 9afa389da..8d4cd8d68 100644
--- a/libempathy/empathy-utils.c
+++ b/libempathy/empathy-utils.c
@@ -58,6 +58,8 @@
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include "empathy-debug.h"
+#define TM "\342\204\242" /* trademark */
+
/* Translation between presence types and string */
static struct {
const gchar *name;
@@ -552,6 +554,7 @@ empathy_protocol_name_to_display_name (const gchar *proto_name)
{ "facebook", N_("Facebook Chat"), TRUE },
{ "groupwise", "GroupWise", FALSE },
{ "sip", "SIP", FALSE },
+ { "skype", "Skype" TM, FALSE },
{ NULL, NULL }
};
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4b5af18b9..a137605e5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,11 +19,13 @@ libempathy-gtk/empathy-account-widget.c
[type: gettext/glade]libempathy-gtk/empathy-account-widget-icq.ui
libempathy-gtk/empathy-account-widget-irc.c
libempathy-gtk/empathy-account-widget-sip.c
+libempathy-gtk/empathy-account-widget-skype.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-local-xmpp.ui
[type: gettext/glade]libempathy-gtk/empathy-account-widget-sip.ui
+[type: gettext/glade]libempathy-gtk/empathy-account-widget-skype.ui
[type: gettext/glade]libempathy-gtk/empathy-account-widget-yahoo.ui
libempathy-gtk/empathy-avatar-chooser.c
libempathy-gtk/empathy-avatar-image.c
diff --git a/src/empathy-account-assistant.c b/src/empathy-account-assistant.c
index e84fa650c..f7753bdb3 100644
--- a/src/empathy-account-assistant.c
+++ b/src/empathy-account-assistant.c
@@ -34,6 +34,7 @@
#include <libempathy/empathy-utils.h>
#include <libempathy-gtk/empathy-account-widget.h>
+#include <libempathy-gtk/empathy-account-widget-skype.h>
#include <libempathy-gtk/empathy-protocol-chooser.h>
#include <libempathy-gtk/empathy-ui-utils.h>
@@ -400,6 +401,15 @@ account_assistant_protocol_changed_cb (GtkComboBox *chooser,
/* we are not ready yet */
return;
+ if (!tp_strdiff (proto->name, "skype"))
+ {
+ if (!empathy_account_widget_skype_show_eula (GTK_WINDOW (self)))
+ {
+ gtk_combo_box_set_active (chooser, 0);
+ return;
+ }
+ }
+
/* Create account */
if (is_gtalk)
name = "gtalk";
diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c
index 3c690c071..6619442a8 100644
--- a/src/empathy-accounts-dialog.c
+++ b/src/empathy-accounts-dialog.c
@@ -46,6 +46,7 @@
#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-account-widget-skype.h>
#include <libempathy-gtk/empathy-cell-renderer-activatable.h>
#include <libempathy-gtk/empathy-images.h>
#include <libempathy-gtk/mx-gtk-light-switch.h>
@@ -257,6 +258,20 @@ accounts_dialog_enable_switch_flipped (MxGtkLightSwitch *sw,
if (account == NULL)
return;
+ if (state == TRUE &&
+ !tp_strdiff (tp_account_get_connection_manager (account), "psyke"))
+ {
+ /* psyke typically doesn't support more than one simultaneous connection
+ * unless you've compiled it to do so */
+ if (!empathy_accounts_dialog_skype_disable_other_accounts (account,
+ GTK_WINDOW (dialog)))
+ {
+ /* user chose not to proceed */
+ mx_gtk_light_switch_set_active (sw, FALSE);
+ return;
+ }
+ }
+
tp_account_set_enabled_async (account, state,
accounts_dialog_enable_account_cb, NULL);
}
@@ -740,6 +755,8 @@ accounts_dialog_protocol_changed_cb (GtkWidget *widget,
GtkTreeIter iter;
gboolean creating;
EmpathyAccountSettings *settings;
+ TpConnectionManager *cm;
+ TpConnectionManagerProtocol *proto;
gchar *account = NULL, *password = NULL;
/* The "changed" signal is fired during the initiation of the
@@ -758,6 +775,25 @@ accounts_dialog_protocol_changed_cb (GtkWidget *widget,
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
return;
+ cm = empathy_protocol_chooser_dup_selected (
+ EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto, NULL, NULL);
+
+ if (cm == NULL)
+ return;
+
+ g_object_unref (cm);
+
+ if (!tp_strdiff (proto->name, "skype"))
+ {
+ if (!empathy_account_widget_skype_show_eula (GTK_WINDOW (dialog)))
+ {
+ gtk_combo_box_set_active (
+ GTK_COMBO_BOX (priv->combobox_protocol), 0);
+ empathy_account_dialog_cancel (dialog);
+ return;
+ }
+ }
+
/* Save "account" and "password" parameters */
g_object_get (priv->setting_widget_object, "settings", &settings, NULL);
diff --git a/src/empathy-chat-manager.c b/src/empathy-chat-manager.c
index 4ff6b7d30..8455001f5 100644
--- a/src/empathy-chat-manager.c
+++ b/src/empathy-chat-manager.c
@@ -216,6 +216,16 @@ handle_channels (TpSimpleHandler *handler,
TpChannel *channel = l->data;
EmpathyTpChat *tp_chat;
+ if (tp_proxy_get_invalidated (channel) != NULL)
+ continue;
+
+ if (!TP_IS_TEXT_CHANNEL (channel))
+ {
+ DEBUG ("Channel %s doesn't implement Messages; can't handle it",
+ tp_proxy_get_object_path (channel));
+ continue;
+ }
+
tp_chat = empathy_tp_chat_new (account, channel);
if (empathy_tp_chat_is_ready (tp_chat))
diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c
index 041d22a18..e2ce0725f 100644
--- a/src/empathy-event-manager.c
+++ b/src/empathy-event-manager.c
@@ -1037,7 +1037,7 @@ approve_channels (TpSimpleApprover *approver,
channel_type = tp_channel_get_channel_type_id (channel);
- if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
+ if (TP_IS_TEXT_CHANNEL (channel))
{
EmpathyTpChat *tp_chat;
diff --git a/src/empathy-map-view.c b/src/empathy-map-view.c
index 31fa997c2..321fbce53 100644
--- a/src/empathy-map-view.c
+++ b/src/empathy-map-view.c
@@ -231,7 +231,7 @@ map_view_contacts_update_label (ChamplainMarker *marker)
gchar *date;
gchar *label;
GValue *gtime;
- time_t loctime;
+ gint64 loctime;
GHashTable *location;
EmpathyContact *contact;
@@ -242,18 +242,24 @@ map_view_contacts_update_label (ChamplainMarker *marker)
if (gtime != NULL)
{
- time_t now;
+ GDateTime *now, *d;
+ GTimeSpan delta;
loctime = g_value_get_int64 (gtime);
date = empathy_time_to_string_relative (loctime);
label = g_strconcat ("<b>", name, "</b>\n<small>", date, "</small>", NULL);
g_free (date);
- now = time (NULL);
+ now = g_date_time_new_now_utc ();
+ d = g_date_time_new_from_unix_utc (loctime);
+ delta = g_date_time_difference (now, d);
/* if location is older than a week */
- if (now - loctime > (60 * 60 * 24 * 7))
- clutter_actor_set_opacity (CLUTTER_ACTOR (marker), 0.75 * 255);
+ if (delta > G_TIME_SPAN_DAY * 7)
+ clutter_actor_set_opacity (marker, 0.75 * 255);
+
+ g_date_time_unref (now);
+ g_date_time_unref (d);
}
else
{
diff --git a/telepathy-yell b/telepathy-yell
-Subproject 47367965cd8f9ed9b72e8660f3f6887546e5992
+Subproject 179a352f0f8a248d54afe0fca93d1a78ccd8d6a