X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy-gtk%2Fempathy-ui-utils.c;h=4503a39cc22f67f12cb613e3d1be4f55df183d46;hp=c737873d130385f79cb973682b009d68ef61882b;hb=4d2d5a1622f93b69af195d7e3c4d4cb424dbec6e;hpb=9ff14672ab605f20789a2db6f9f89673cf8f2c4b diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c index c737873d..4503a39c 100644 --- a/libempathy-gtk/empathy-ui-utils.c +++ b/libempathy-gtk/empathy-ui-utils.c @@ -50,16 +50,6 @@ #include #include -#define SCHEMES "([a-zA-Z\\+]+)" -#define INVALID_CHARS " \n\"'" -#define INVALID_CHARS_EXT INVALID_CHARS "\\[\\]<>(){},;:?" -#define BODY "([^"INVALID_CHARS"]+)" -#define BODY_END "([^"INVALID_CHARS"]*)[^"INVALID_CHARS_EXT".]" -#define BODY_STRICT "([^"INVALID_CHARS_EXT"]+)" -#define URI_REGEX "("SCHEMES"://"BODY_END")" \ - "|((www|ftp)\\."BODY_END")" \ - "|((mailto:)?"BODY_STRICT"@"BODY"\\."BODY_END")" - void empathy_gtk_init (void) { @@ -75,19 +65,6 @@ empathy_gtk_init (void) initialized = TRUE; } -GRegex * -empathy_uri_regex_dup_singleton (void) -{ - static GRegex *uri_regex = NULL; - - /* We intentionally leak the regex so it's not recomputed */ - if (!uri_regex) { - uri_regex = g_regex_new (URI_REGEX, 0, 0, NULL); - } - - return g_regex_ref (uri_regex); -} - static GtkBuilder * builder_get_file_valist (const gchar *filename, const gchar *first_object, @@ -230,6 +207,21 @@ empathy_icon_name_for_contact (EmpathyContact *contact) return empathy_icon_name_for_presence (presence); } +const gchar * +empathy_protocol_name_for_contact (EmpathyContact *contact) +{ + TpAccount *account; + + g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); + + account = empathy_contact_get_account (contact); + if (account == NULL) { + return NULL; + } + + return tp_account_get_icon_name (account); +} + GdkPixbuf * empathy_pixbuf_from_data (gchar *data, gsize data_size) @@ -490,6 +482,104 @@ empathy_pixbuf_avatar_from_contact_scaled (EmpathyContact *contact, return empathy_pixbuf_from_avatar_scaled (avatar, width, height); } +GdkPixbuf * +empathy_pixbuf_contact_status_icon (EmpathyContact *contact, + gboolean show_protocol) +{ + const gchar *icon_name; + + g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); + + icon_name = empathy_icon_name_for_contact (contact); + + if (icon_name == NULL) { + return NULL; + } + return empathy_pixbuf_contact_status_icon_with_icon_name (contact, + icon_name, + show_protocol); +} + +GdkPixbuf * +empathy_pixbuf_contact_status_icon_with_icon_name (EmpathyContact *contact, + const gchar *icon_name, + gboolean show_protocol) +{ + GdkPixbuf *pix_status; + GdkPixbuf *pix_protocol; + gchar *icon_filename; + gint height, width; + gint numerator, denominator; + + g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); + g_return_val_if_fail (icon_name != NULL, NULL); + + numerator = 3; + denominator = 4; + + icon_filename = empathy_filename_from_icon_name (icon_name, + GTK_ICON_SIZE_MENU); + if (icon_filename == NULL) { + DEBUG ("icon name: %s could not be found\n", icon_name); + return NULL; + } + + pix_status = gdk_pixbuf_new_from_file (icon_filename, NULL); + + g_free (icon_filename); + + if (pix_status == NULL) { + DEBUG ("Could not open icon %s\n", icon_filename); + return NULL; + } + + if (!show_protocol) + return pix_status; + + height = gdk_pixbuf_get_height (pix_status); + width = gdk_pixbuf_get_width (pix_status); + + pix_protocol = empathy_pixbuf_protocol_from_contact_scaled (contact, + width * numerator / denominator, + height * numerator / denominator); + + if (pix_protocol == NULL) { + return pix_status; + } + gdk_pixbuf_composite (pix_protocol, pix_status, + 0, height - height * numerator / denominator, + width * numerator / denominator, height * numerator / denominator, + 0, height - height * numerator / denominator, + 1, 1, + GDK_INTERP_BILINEAR, 255); + + g_object_unref (pix_protocol); + + return pix_status; +} + +GdkPixbuf * +empathy_pixbuf_protocol_from_contact_scaled (EmpathyContact *contact, + gint width, + gint height) +{ + TpAccount *account; + gchar *filename; + GdkPixbuf *pixbuf = NULL; + + g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); + + account = empathy_contact_get_account (contact); + filename = empathy_filename_from_icon_name (tp_account_get_icon_name (account), + GTK_ICON_SIZE_MENU); + if (filename != NULL) { + pixbuf = gdk_pixbuf_new_from_file_at_size (filename, width, height, NULL); + g_free (filename); + } + + return pixbuf; +} + GdkPixbuf * empathy_pixbuf_scale_down_if_necessary (GdkPixbuf *pixbuf, gint max_size) { @@ -1283,7 +1373,8 @@ empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon) XChangeProperty (dpy, GDK_WINDOW_XID (gdk_window), - gdk_x11_get_xatom_by_name_for_display (gdk_drawable_get_display (gdk_window), + gdk_x11_get_xatom_by_name_for_display ( + gdk_drawable_get_display (gdk_window), "_NET_WM_ICON_GEOMETRY"), XA_CARDINAL, 32, PropModeReplace, (guchar *)&data, 4); @@ -1294,11 +1385,10 @@ empathy_window_iconify (GtkWindow *window, GtkStatusIcon *status_icon) /* Takes care of moving the window to the current workspace. */ void -empathy_window_present (GtkWindow *window, - gboolean steal_focus) +empathy_window_present (GtkWindow *window) { - guint32 timestamp; GdkWindow *gdk_window; + guint32 timestamp; g_return_if_fail (GTK_IS_WINDOW (window)); @@ -1321,6 +1411,10 @@ empathy_window_present (GtkWindow *window, } timestamp = gtk_get_current_event_time (); + if (timestamp == 0) + /* No event, fallback to _NET_WM_USER_TIME */ + timestamp = gdk_x11_display_get_user_time (gdk_display_get_default ()); + gtk_window_present_with_time (window, timestamp); gtk_window_set_skip_taskbar_hint (window, FALSE); gtk_window_deiconify (window); @@ -1442,16 +1536,55 @@ empathy_link_button_new (const gchar *url, } void -empathy_toggle_button_set_state_quietly (GtkWidget *widget, - GCallback callback, - gpointer user_data, - gboolean active) +empathy_send_file (EmpathyContact *contact, GFile *file) { - g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget)); + EmpathyFTFactory *factory; + GtkRecentManager *manager; + gchar *uri; + + g_return_if_fail (EMPATHY_IS_CONTACT (contact)); + g_return_if_fail (G_IS_FILE (file)); + + factory = empathy_ft_factory_dup_singleton (); - g_signal_handlers_block_by_func (widget, callback, user_data); - g_object_set (widget, "active", active, NULL); - g_signal_handlers_unblock_by_func (widget, callback, user_data); + empathy_ft_factory_new_transfer_outgoing (factory, contact, file); + + uri = g_file_get_uri (file); + manager = gtk_recent_manager_get_default (); + gtk_recent_manager_add_item (manager, uri); + g_free (uri); + + g_object_unref (factory); +} + +void +empathy_send_file_from_uri_list (EmpathyContact *contact, const gchar *uri_list) +{ + const gchar *nl; + GFile *file; + + /* Only handle a single file for now. It would be wicked cool to be + able to do multiple files, offering to zip them or whatever like + nautilus-sendto does. Note that text/uri-list is defined to have + each line terminated by \r\n, but we can be tolerant of applications + that only use \n or don't terminate single-line entries. + */ + nl = strstr (uri_list, "\r\n"); + if (!nl) { + nl = strchr (uri_list, '\n'); + } + if (nl) { + gchar *uri = g_strndup (uri_list, nl - uri_list); + file = g_file_new_for_uri (uri); + g_free (uri); + } + else { + file = g_file_new_for_uri (uri_list); + } + + empathy_send_file (contact, file); + + g_object_unref (file); } static void @@ -1459,25 +1592,13 @@ file_manager_send_file_response_cb (GtkDialog *widget, gint response_id, EmpathyContact *contact) { - EmpathyFTFactory *factory; GFile *file; - gchar *uri; - GtkRecentManager *manager; if (response_id == GTK_RESPONSE_OK) { file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (widget)); - uri = g_file_get_uri (file); - factory = empathy_ft_factory_dup_singleton (); - - empathy_ft_factory_new_transfer_outgoing (factory, contact, - file); + empathy_send_file (contact, file); - manager = gtk_recent_manager_get_default (); - gtk_recent_manager_add_item (manager, uri); - - g_free (uri); - g_object_unref (factory); g_object_unref (file); } @@ -1515,6 +1636,9 @@ empathy_send_file_with_file_chooser (EmpathyContact *contact) gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), FALSE); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), + g_get_home_dir ()); + g_signal_connect (widget, "response", G_CALLBACK (file_manager_send_file_response_cb), contact); @@ -1553,6 +1677,7 @@ void empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler) { GtkWidget *widget; + const gchar *dir; widget = gtk_file_chooser_dialog_new (_("Select a destination"), NULL, @@ -1567,113 +1692,16 @@ empathy_receive_file_with_file_chooser (EmpathyFTHandler *handler) gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (widget), TRUE); + dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD); + if (dir == NULL) + /* Fallback to $HOME if $XDG_DOWNLOAD_DIR is not set */ + dir = g_get_home_dir (); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), dir); + g_signal_connect (widget, "response", G_CALLBACK (file_manager_receive_file_response_cb), handler); gtk_widget_show (widget); } -void -empathy_string_parser_substr (const gchar *text, - gssize len, - EmpathyStringParser *parsers, - gpointer user_data) -{ - if (parsers != NULL && parsers[0].match_func != NULL) { - parsers[0].match_func (text, len, - parsers[0].replace_func, parsers + 1, - user_data); - } -} - -void -empathy_string_match_link (const gchar *text, - gssize len, - EmpathyStringReplace replace_func, - EmpathyStringParser *sub_parsers, - gpointer user_data) -{ - GRegex *uri_regex; - GMatchInfo *match_info; - gboolean match; - gint last = 0; - - uri_regex = empathy_uri_regex_dup_singleton (); - match = g_regex_match_full (uri_regex, text, len, 0, 0, &match_info, NULL); - if (match) { - gint s = 0, e = 0; - - do { - g_match_info_fetch_pos (match_info, 0, &s, &e); - - if (s > last) { - /* Append the text between last link (or the - * start of the message) and this link */ - empathy_string_parser_substr (text + last, - s - last, - sub_parsers, - user_data); - } - - replace_func (text + s, e - s, NULL, user_data); - - last = e; - } while (g_match_info_next (match_info, NULL)); - } - - empathy_string_parser_substr (text + last, len - last, - sub_parsers, user_data); - - g_match_info_free (match_info); - g_regex_unref (uri_regex); -} - -void -empathy_string_match_smiley (const gchar *text, - gssize len, - EmpathyStringReplace replace_func, - EmpathyStringParser *sub_parsers, - gpointer user_data) -{ - guint last = 0; - EmpathySmileyManager *smiley_manager; - GSList *hits, *l; - - smiley_manager = empathy_smiley_manager_dup_singleton (); - hits = empathy_smiley_manager_parse_len (smiley_manager, text, len); - - for (l = hits; l; l = l->next) { - EmpathySmileyHit *hit = l->data; - - if (hit->start > last) { - /* Append the text between last smiley (or the - * start of the message) and this smiley */ - empathy_string_parser_substr (text + last, - hit->start - last, - sub_parsers, user_data); - } - - replace_func (text + hit->start, hit->end - hit->start, - hit, user_data); - - last = hit->end; - - empathy_smiley_hit_free (hit); - } - g_slist_free (hits); - g_object_unref (smiley_manager); - - empathy_string_parser_substr (text + last, len - last, - sub_parsers, user_data); -} - -void -empathy_string_match_all (const gchar *text, - gssize len, - EmpathyStringReplace replace_func, - EmpathyStringParser *sub_parsers, - gpointer user_data) -{ - replace_func (text, len, NULL, user_data); -} -