*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
* Authors: Mikael Hallendal <micke@imendio.com>
* Richard Hult <richard@imendio.com>
* Martyn Russell <martyn@imendio.com>
* Xavier Claessens <xclaesse@gmail.com>
* Jonny Lamb <jonny.lamb@collabora.co.uk>
- *
+ *
* Part of this file is copied from GtkSourceView (gtksourceiter.c):
* Paolo Maggi
* Jeroen Zwartepoorte
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
-#include <glade/glade.h>
-
-#include <libmissioncontrol/mc-profile.h>
#include "empathy-ui-utils.h"
#include "empathy-images.h"
+#include "empathy-conf.h"
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include <libempathy/empathy-debug.h>
#include <libempathy/empathy-utils.h>
#include <libempathy/empathy-dispatcher.h>
+#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-ft-factory.h>
+
+#define SCHEMES "(https?|s?ftps?|nntp|news|javascript|about|ghelp|apt|telnet|"\
+ "file|webcal|mailto)"
+#define BODY "([^\\ \\n]+)"
+#define END_BODY "([^\\ \\n]*[^,;\?><()\\ \"\\.\\n])"
+#define URI_REGEX "("SCHEMES"://"END_BODY")" \
+ "|((mailto:)?"BODY"@"BODY"\\."END_BODY")"\
+ "|((www|ftp)\\."END_BODY")"
void
-empathy_gtk_init (int *argc, char ***argv)
+empathy_gtk_init (void)
{
static gboolean initialized = FALSE;
return;
empathy_init ();
- gtk_init (argc, argv);
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
PKGDATADIR G_DIR_SEPARATOR_S "icons");
initialized = TRUE;
}
-gboolean
-empathy_gtk_init_with_args (int *argc,
- char ***argv,
- char *parameter_string,
- GOptionEntry *entries,
- char *translation_domain,
- GError **error)
+GRegex *
+empathy_uri_regex_dup_singleton (void)
{
- static gboolean initialized = FALSE;
- gboolean ret;
-
- if (initialized)
- return TRUE;
+ static GRegex *uri_regex = NULL;
- empathy_init ();
- ret = gtk_init_with_args (argc, argv, parameter_string, entries,
- translation_domain, error);
- gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
- PKGDATADIR G_DIR_SEPARATOR_S "icons");
-
- initialized = TRUE;
+ /* We intentionally leak the regex so it's not recomputed */
+ if (!uri_regex) {
+ uri_regex = g_regex_new (URI_REGEX, 0, 0, NULL);
+ }
- return ret;
+ return g_regex_ref (uri_regex);
}
-struct SizeData {
- gint width;
- gint height;
- gboolean preserve_aspect_ratio;
-};
-
-static GladeXML *
-get_glade_file (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget,
- va_list args)
+static GtkBuilder *
+builder_get_file_valist (const gchar *filename,
+ const gchar *first_object,
+ va_list args)
{
- GladeXML *gui;
- const char *name;
- GtkWidget **widget_ptr;
-
- DEBUG ("Loading glade file %s", filename);
+ GtkBuilder *gui;
+ const gchar *name;
+ GObject **object_ptr;
+ GError *error = NULL;
- gui = glade_xml_new (filename, root, domain);
+ DEBUG ("Loading file %s", filename);
- if (!gui) {
- g_warning ("Couldn't find necessary glade file '%s'", filename);
+ gui = gtk_builder_new ();
+ if (!gtk_builder_add_from_file (gui, filename, &error)) {
+ g_critical ("GtkBuilder Error: %s", error->message);
+ g_clear_error (&error);
+ g_object_unref (gui);
+ return NULL;
}
- for (name = first_required_widget; name; name = va_arg (args, char *)) {
- widget_ptr = va_arg (args, void *);
+ for (name = first_object; name; name = va_arg (args, const gchar *)) {
+ object_ptr = va_arg (args, GObject**);
- *widget_ptr = glade_xml_get_widget (gui, name);
+ *object_ptr = gtk_builder_get_object (gui, name);
- if (!*widget_ptr) {
- g_warning ("Glade file '%s' is missing widget '%s'.",
- filename, name);
+ if (!*object_ptr) {
+ g_warning ("File is missing object '%s'.", name);
continue;
}
}
return gui;
}
-void
-empathy_glade_get_file_simple (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget, ...)
-{
- va_list args;
- GladeXML *gui;
-
- va_start (args, first_required_widget);
-
- gui = get_glade_file (filename,
- root,
- domain,
- first_required_widget,
- args);
-
- va_end (args);
-
- if (gui) {
- g_object_unref (gui);
- }
-}
-
-GladeXML *
-empathy_glade_get_file (const gchar *filename,
- const gchar *root,
- const gchar *domain,
- const gchar *first_required_widget, ...)
+GtkBuilder *
+empathy_builder_get_file (const gchar *filename,
+ const gchar *first_object,
+ ...)
{
- va_list args;
- GladeXML *gui;
-
- va_start (args, first_required_widget);
-
- gui = get_glade_file (filename,
- root,
- domain,
- first_required_widget,
- args);
+ GtkBuilder *gui;
+ va_list args;
+ va_start (args, first_object);
+ gui = builder_get_file_valist (filename, first_object, args);
va_end (args);
- if (!gui) {
- return NULL;
- }
-
return gui;
}
void
-empathy_glade_connect (GladeXML *gui,
- gpointer user_data,
- gchar *first_widget, ...)
+empathy_builder_connect (GtkBuilder *gui,
+ gpointer user_data,
+ gchar *first_object,
+ ...)
{
va_list args;
const gchar *name;
const gchar *signal;
- GtkWidget *widget;
- gpointer *callback;
-
- va_start (args, first_widget);
-
- for (name = first_widget; name; name = va_arg (args, char *)) {
- signal = va_arg (args, void *);
- callback = va_arg (args, void *);
-
- widget = glade_xml_get_widget (gui, name);
- if (!widget) {
- g_warning ("Glade file is missing widget '%s', aborting",
- name);
- continue;
- }
-
- g_signal_connect (widget,
- signal,
- G_CALLBACK (callback),
- user_data);
- }
-
- va_end (args);
-}
-
-void
-empathy_glade_setup_size_group (GladeXML *gui,
- GtkSizeGroupMode mode,
- gchar *first_widget, ...)
-{
- va_list args;
- GtkWidget *widget;
- GtkSizeGroup *size_group;
- const gchar *name;
-
- va_start (args, first_widget);
+ GObject *object;
+ GCallback callback;
- size_group = gtk_size_group_new (mode);
+ va_start (args, first_object);
+ for (name = first_object; name; name = va_arg (args, const gchar *)) {
+ signal = va_arg (args, const gchar *);
+ callback = va_arg (args, GCallback);
- for (name = first_widget; name; name = va_arg (args, char *)) {
- widget = glade_xml_get_widget (gui, name);
- if (!widget) {
- g_warning ("Glade file is missing widget '%s'", name);
+ object = gtk_builder_get_object (gui, name);
+ if (!object) {
+ g_warning ("File is missing object '%s'.", name);
continue;
}
- gtk_size_group_add_widget (size_group, widget);
+ g_signal_connect (object, signal, callback, user_data);
}
- g_object_unref (size_group);
-
va_end (args);
}
-const gchar *
-empathy_icon_name_from_account (McAccount *account)
+GtkWidget *
+empathy_builder_unref_and_keep_widget (GtkBuilder *gui,
+ GtkWidget *widget)
{
- McProfile *profile;
+ /* On construction gui sinks the initial reference to widget. When gui
+ * is finalized it will drop its ref to widget. We take our own ref to
+ * prevent widget being finalised. The widget is forced to have a
+ * floating reference, like when it was initially unowned so that it can
+ * be used like any other GtkWidget. */
- profile = mc_account_get_profile (account);
+ g_object_ref (widget);
+ g_object_force_floating (G_OBJECT (widget));
+ g_object_unref (gui);
- return mc_profile_get_icon_name (profile);
+ return widget;
}
const gchar *
-empathy_icon_name_for_presence (McPresence presence)
+empathy_icon_name_for_presence (TpConnectionPresenceType presence)
{
switch (presence) {
- case MC_PRESENCE_AVAILABLE:
+ case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
return EMPATHY_IMAGE_AVAILABLE;
- case MC_PRESENCE_DO_NOT_DISTURB:
+ case TP_CONNECTION_PRESENCE_TYPE_BUSY:
return EMPATHY_IMAGE_BUSY;
- case MC_PRESENCE_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_AWAY:
return EMPATHY_IMAGE_AWAY;
- case MC_PRESENCE_EXTENDED_AWAY:
+ case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
return EMPATHY_IMAGE_EXT_AWAY;
- case MC_PRESENCE_HIDDEN:
+ case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
return EMPATHY_IMAGE_HIDDEN;
- case MC_PRESENCE_OFFLINE:
- case MC_PRESENCE_UNSET:
+ case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
+ case TP_CONNECTION_PRESENCE_TYPE_ERROR:
+ case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
return EMPATHY_IMAGE_OFFLINE;
- default:
- g_assert_not_reached ();
+ case TP_CONNECTION_PRESENCE_TYPE_UNSET:
+ return NULL;
}
return NULL;
const gchar *
empathy_icon_name_for_contact (EmpathyContact *contact)
{
- McPresence presence;
+ TpConnectionPresenceType presence;
g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
EMPATHY_IMAGE_OFFLINE);
return pixbuf;
}
+struct SizeData {
+ gint width;
+ gint height;
+ gboolean preserve_aspect_ratio;
+};
+
static void
pixbuf_from_avatar_size_prepared_cb (GdkPixbufLoader *loader,
int width,
}
GdkPixbuf *
-empathy_pixbuf_from_icon_name (const gchar *icon_name,
- GtkIconSize icon_size)
+empathy_pixbuf_from_icon_name_sized (const gchar *icon_name,
+ gint size)
{
- GtkIconTheme *theme;
- GdkPixbuf *pixbuf = NULL;
- GError *error = NULL;
- gint w, h;
- gint size = 48;
+ GtkIconTheme *theme;
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
if (!icon_name) {
return NULL;
theme = gtk_icon_theme_get_default ();
- if (gtk_icon_size_lookup (icon_size, &w, &h)) {
- size = (w + h) / 2;
- }
-
pixbuf = gtk_icon_theme_load_icon (theme,
icon_name,
size,
return pixbuf;
}
+GdkPixbuf *
+empathy_pixbuf_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ gint w, h;
+ gint size = 48;
+
+ if (!icon_name) {
+ return NULL;
+ }
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ return empathy_pixbuf_from_icon_name_sized (icon_name, size);
+}
+
+gchar *
+empathy_filename_from_icon_name (const gchar *icon_name,
+ GtkIconSize icon_size)
+{
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
+ gint w, h;
+ gint size = 48;
+ gchar *ret;
+
+ icon_theme = gtk_icon_theme_get_default ();
+
+ if (gtk_icon_size_lookup (icon_size, &w, &h)) {
+ size = (w + h) / 2;
+ }
+
+ icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0);
+ ret = g_strdup (gtk_icon_info_get_filename (icon_info));
+ gtk_icon_info_free (icon_info);
+
+ return ret;
+}
+
/* Stolen from GtkSourceView, hence the weird intendation. Please keep it like
* that to make it easier to apply changes from the original code.
*/
if (needle_len == 0)
{
- ret = (gchar *)haystack;
+ ret = (gchar *) haystack;
goto finally_1;
}
goto finally_1;
}
- p = (gchar*)caseless_haystack;
+ p = (gchar *) caseless_haystack;
needle_len = strlen (needle);
i = 0;
/* being UTF8 correct sucks; this accounts for extra
offsets coming from canonical decompositions of
UTF8 characters (e.g. accented characters) which
- g_utf8_normalize() performs */
+ g_utf8_normalize () performs */
gchar *normal;
gchar buffer[6];
gint buffer_len;
}
} while (gtk_text_iter_forward_line (&search));
- g_strfreev ((gchar**)lines);
+ g_strfreev ((gchar **) lines);
return retval;
}
if (needle_len == 0)
{
- ret = (gchar *)haystack;
+ ret = (gchar *) haystack;
goto finally_1;
}
}
}
- g_strfreev ((gchar**)lines);
+ g_strfreev ((gchar **) lines);
return retval;
}
return TRUE;
}
-void
+void
empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon)
{
GdkRectangle icon_location;
}
timestamp = gtk_get_current_event_time ();
- gtk_window_set_skip_taskbar_hint (window, FALSE);
gtk_window_present_with_time (window, timestamp);
+ gtk_window_set_skip_taskbar_hint (window, FALSE);
/* FIXME: This shouldn't be required as gtk_window_present's doc says
* it deiconify automatically. */
gtk_window_deiconify (window);
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL, 0,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
_("Unable to open URI"));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_handlers_unblock_by_func (widget, callback, user_data);
}
-GtkTextTag *
-empathy_text_buffer_tag_set (GtkTextBuffer *buffer,
- const gchar *tag_name,
- const gchar *first_property_name,
- ...)
-{
- GtkTextTagTable *table;
- GtkTextTag *tag;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (tag_name != NULL, NULL);
-
- table = gtk_text_buffer_get_tag_table (buffer);
- tag = gtk_text_tag_table_lookup (table, tag_name);
-
- if (!tag) {
- tag = gtk_text_tag_new (tag_name);
- gtk_text_tag_table_add (table, tag);
- g_object_unref (tag);
- } else {
- /* Clear the old values so that we don't affect the new theme. */
- g_object_set (tag,
- "background-set", FALSE,
- "foreground-set", FALSE,
- "invisible-set", FALSE,
- "justification-set", FALSE,
- "paragraph-background-set", FALSE,
- "pixels-above-lines-set", FALSE,
- "pixels-below-lines-set", FALSE,
- "rise-set", FALSE,
- "scale-set", FALSE,
- "size-set", FALSE,
- "style-set", FALSE,
- "weight-set", FALSE,
- NULL);
- }
-
- if (first_property_name) {
- va_list list;
-
- va_start (list, first_property_name);
- g_object_set_valist (G_OBJECT (tag), first_property_name, list);
- va_end (list);
- }
-
- return tag;
-}
-
-/* Sending files with the file chooser */
-
static void
file_manager_send_file_response_cb (GtkDialog *widget,
gint response_id,
EmpathyContact *contact)
{
- if (response_id == GTK_RESPONSE_OK) {
- GSList *list;
- GSList *l;
-
- list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (widget));
-
- DEBUG ("File chooser selected files:");
+ EmpathyFTFactory *factory;
+ GFile *file;
+ gchar *uri;
+ GtkRecentManager *manager;
- for (l = list; l; l = l->next) {
- gchar *uri;
- GFile *gfile;
- GtkRecentManager *manager;
+ if (response_id == GTK_RESPONSE_OK) {
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget));
+ uri = g_file_get_uri (file);
- uri = l->data;
- gfile = g_file_new_for_uri (uri);
+ factory = empathy_ft_factory_dup_singleton ();
- DEBUG ("\t%s", uri);
- empathy_dispatcher_send_file (contact, gfile);
+ empathy_ft_factory_new_transfer_outgoing (factory, contact,
+ file);
- manager = gtk_recent_manager_get_default ();
- gtk_recent_manager_add_item (manager, uri);
+ manager = gtk_recent_manager_get_default ();
+ gtk_recent_manager_add_item (manager, uri);
- g_object_unref (gfile);
- g_free (uri);
- }
- g_slist_free (list);
+ g_free (uri);
+ g_object_unref (factory);
+ g_object_unref (file);
}
gtk_widget_destroy (GTK_WIDGET (widget));
gtk_widget_show (widget);
}
+
+static void
+file_manager_receive_file_response_cb (GtkDialog *dialog,
+ GtkResponseType response,
+ EmpathyFTHandler *handler)
+{
+ EmpathyFTFactory *factory;
+ GFile *file;
+
+ if (response == GTK_RESPONSE_OK) {
+ factory = empathy_ft_factory_dup_singleton ();
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ empathy_ft_factory_set_destination_for_incoming_handler
+ (factory, handler, file);
+
+ g_object_unref (factory);
+ g_object_unref (file);
+ } else {
+ /* unref the handler, as we dismissed the file chooser,
+ * and refused the transfer.
+ */
+ g_object_unref (handler);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+void
+empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler)
+{
+ GtkWidget *widget;
+
+ widget = gtk_file_chooser_dialog_new (_("Select a destination"),
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE,
+ GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (widget),
+ empathy_ft_handler_get_filename (handler));
+ gtk_file_chooser_set_do_overwrite_confirmation
+ (GTK_FILE_CHOOSER (widget), TRUE);
+
+ g_signal_connect (widget, "response",
+ G_CALLBACK (file_manager_receive_file_response_cb), handler);
+
+ gtk_widget_show (widget);
+}