| 1637 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) { |
1635 else if (purple_str_has_suffix(basename, ".desktop") && (item = purple_desktop_item_new_from_file(filename))) { |
| 1638 PurpleDesktopItemType dtype; |
1636 PurpleDesktopItemType dtype; |
| 1639 char key[64]; |
1637 char key[64]; |
| 1640 const char *itemname = NULL; |
1638 const char *itemname = NULL; |
| 1641 |
1639 |
| 1642 #if GTK_CHECK_VERSION(2,6,0) |
|
| 1643 const char * const *langs; |
1640 const char * const *langs; |
| 1644 int i; |
1641 int i; |
| 1645 langs = g_get_language_names(); |
1642 langs = g_get_language_names(); |
| 1646 for (i = 0; langs[i]; i++) { |
1643 for (i = 0; langs[i]; i++) { |
| 1647 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]); |
1644 g_snprintf(key, sizeof(key), "Name[%s]", langs[i]); |
| 1648 itemname = purple_desktop_item_get_string(item, key); |
1645 itemname = purple_desktop_item_get_string(item, key); |
| 1649 break; |
1646 break; |
| 1650 } |
1647 } |
| 1651 #else |
1648 |
| 1652 const char *lang = g_getenv("LANG"); |
|
| 1653 char *dot; |
|
| 1654 dot = strchr(lang, '.'); |
|
| 1655 if (dot) |
|
| 1656 *dot = '\0'; |
|
| 1657 g_snprintf(key, sizeof(key), "Name[%s]", lang); |
|
| 1658 itemname = purple_desktop_item_get_string(item, key); |
|
| 1659 #endif |
|
| 1660 if (!itemname) |
1649 if (!itemname) |
| 1661 itemname = purple_desktop_item_get_string(item, "Name"); |
1650 itemname = purple_desktop_item_get_string(item, "Name"); |
| 1662 |
1651 |
| 1663 dtype = purple_desktop_item_get_entry_type(item); |
1652 dtype = purple_desktop_item_get_entry_type(item); |
| 1664 switch (dtype) { |
1653 switch (dtype) { |
| 1671 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry), |
1660 gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry), |
| 1672 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer), |
1661 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer), |
| 1673 purple_desktop_item_get_string(item, "URL"), itemname); |
1662 purple_desktop_item_get_string(item, "URL"), itemname); |
| 1674 break; |
1663 break; |
| 1675 default: |
1664 default: |
| 1676 /* I don't know if we really want to do anything here. Most of the desktop item types are crap like |
1665 /* I don't know if we really want to do anything here. Most of |
| 1677 * "MIME Type" (I have no clue how that would be a desktop item) and "Comment"... nothing we can really |
1666 * the desktop item types are crap like "MIME Type" (I have no |
| 1678 * send. The only logical one is "Application," but do we really want to send a binary and nothing else? |
1667 * clue how that would be a desktop item) and "Comment"... |
| 1679 * Probably not. I'll just give an error and return. */ |
1668 * nothing we can really send. The only logical one is |
| |
1669 * "Application," but do we really want to send a binary and |
| |
1670 * nothing else? Probably not. I'll just give an error and |
| |
1671 * return. */ |
| 1680 /* The original patch sent the icon used by the launcher. That's probably wrong */ |
1672 /* The original patch sent the icon used by the launcher. That's probably wrong */ |
| 1681 purple_notify_error(NULL, NULL, _("Cannot send launcher"), |
1673 purple_notify_error(NULL, NULL, _("Cannot send launcher"), |
| 1682 _("You dragged a desktop launcher. Most " |
1674 _("You dragged a desktop launcher. Most " |
| 1683 "likely you wanted to send the target " |
1675 "likely you wanted to send the target " |
| 1684 "of this launcher instead of this " |
1676 "of this launcher instead of this " |
| 1863 } |
1855 } |
| 1864 purple_menu_action_free(act); |
1856 purple_menu_action_free(act); |
| 1865 return menuitem; |
1857 return menuitem; |
| 1866 } |
1858 } |
| 1867 |
1859 |
| 1868 #if GTK_CHECK_VERSION(2,3,0) |
|
| 1869 # define NEW_STYLE_COMPLETION |
|
| 1870 #endif |
|
| 1871 |
|
| 1872 typedef struct |
1860 typedef struct |
| 1873 { |
1861 { |
| 1874 GtkWidget *entry; |
1862 GtkWidget *entry; |
| 1875 GtkWidget *accountopt; |
1863 GtkWidget *accountopt; |
| 1876 |
1864 |
| 1877 PidginFilterBuddyCompletionEntryFunc filter_func; |
1865 PidginFilterBuddyCompletionEntryFunc filter_func; |
| 1878 gpointer filter_func_user_data; |
1866 gpointer filter_func_user_data; |
| 1879 |
1867 |
| 1880 #ifdef NEW_STYLE_COMPLETION |
|
| 1881 GtkListStore *store; |
1868 GtkListStore *store; |
| 1882 #else |
|
| 1883 GCompletion *completion; |
|
| 1884 gboolean completion_started; |
|
| 1885 GList *log_items; |
|
| 1886 #endif /* NEW_STYLE_COMPLETION */ |
|
| 1887 } PidginCompletionData; |
1869 } PidginCompletionData; |
| 1888 |
1870 |
| 1889 #ifndef NEW_STYLE_COMPLETION |
|
| 1890 static gboolean |
|
| 1891 completion_entry_event(GtkEditable *entry, GdkEventKey *event, |
|
| 1892 PidginCompletionData *data) |
|
| 1893 { |
|
| 1894 int pos, end_pos; |
|
| 1895 |
|
| 1896 if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Tab) |
|
| 1897 { |
|
| 1898 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); |
|
| 1899 |
|
| 1900 if (data->completion_started && |
|
| 1901 pos != end_pos && pos > 1 && |
|
| 1902 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1903 { |
|
| 1904 gtk_editable_select_region(entry, 0, 0); |
|
| 1905 gtk_editable_set_position(entry, -1); |
|
| 1906 |
|
| 1907 return TRUE; |
|
| 1908 } |
|
| 1909 } |
|
| 1910 else if (event->type == GDK_KEY_PRESS && event->length > 0) |
|
| 1911 { |
|
| 1912 char *prefix, *nprefix; |
|
| 1913 |
|
| 1914 gtk_editable_get_selection_bounds(entry, &pos, &end_pos); |
|
| 1915 |
|
| 1916 if (data->completion_started && |
|
| 1917 pos != end_pos && pos > 1 && |
|
| 1918 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1919 { |
|
| 1920 char *temp; |
|
| 1921 |
|
| 1922 temp = gtk_editable_get_chars(entry, 0, pos); |
|
| 1923 prefix = g_strconcat(temp, event->string, NULL); |
|
| 1924 g_free(temp); |
|
| 1925 } |
|
| 1926 else if (pos == end_pos && pos > 1 && |
|
| 1927 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) |
|
| 1928 { |
|
| 1929 prefix = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), |
|
| 1930 event->string, NULL); |
|
| 1931 } |
|
| 1932 else |
|
| 1933 return FALSE; |
|
| 1934 |
|
| 1935 pos = strlen(prefix); |
|
| 1936 nprefix = NULL; |
|
| 1937 |
|
| 1938 g_completion_complete(data->completion, prefix, &nprefix); |
|
| 1939 |
|
| 1940 if (nprefix != NULL) |
|
| 1941 { |
|
| 1942 gtk_entry_set_text(GTK_ENTRY(entry), nprefix); |
|
| 1943 gtk_editable_set_position(entry, pos); |
|
| 1944 gtk_editable_select_region(entry, pos, -1); |
|
| 1945 |
|
| 1946 data->completion_started = TRUE; |
|
| 1947 |
|
| 1948 g_free(nprefix); |
|
| 1949 g_free(prefix); |
|
| 1950 |
|
| 1951 return TRUE; |
|
| 1952 } |
|
| 1953 |
|
| 1954 g_free(prefix); |
|
| 1955 } |
|
| 1956 |
|
| 1957 return FALSE; |
|
| 1958 } |
|
| 1959 |
|
| 1960 static void |
|
| 1961 destroy_completion_data(GtkWidget *w, PidginCompletionData *data) |
|
| 1962 { |
|
| 1963 g_list_foreach(data->completion->items, (GFunc)g_free, NULL); |
|
| 1964 g_completion_free(data->completion); |
|
| 1965 |
|
| 1966 g_free(data); |
|
| 1967 } |
|
| 1968 #endif /* !NEW_STYLE_COMPLETION */ |
|
| 1969 |
|
| 1970 #ifdef NEW_STYLE_COMPLETION |
|
| 1971 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion, |
1871 static gboolean buddyname_completion_match_func(GtkEntryCompletion *completion, |
| 1972 const gchar *key, GtkTreeIter *iter, gpointer user_data) |
1872 const gchar *key, GtkTreeIter *iter, gpointer user_data) |
| 1973 { |
1873 { |
| 1974 GtkTreeModel *model; |
1874 GtkTreeModel *model; |
| 1975 GValue val1; |
1875 GValue val1; |
| 2114 PidginBuddyCompletionEntry entry; |
2013 PidginBuddyCompletionEntry entry; |
| 2115 entry.is_buddy = FALSE; |
2014 entry.is_buddy = FALSE; |
| 2116 entry.entry.logged_buddy = set; |
2015 entry.entry.logged_buddy = set; |
| 2117 |
2016 |
| 2118 if (filter_func(&entry, user_data)) { |
2017 if (filter_func(&entry, user_data)) { |
| 2119 #ifdef NEW_STYLE_COMPLETION |
|
| 2120 add_buddyname_autocomplete_entry(data->store, |
2018 add_buddyname_autocomplete_entry(data->store, |
| 2121 NULL, NULL, set->account, set->name); |
2019 NULL, NULL, set->account, set->name); |
| 2122 #else |
|
| 2123 /* Steal the name for the GCompletion. */ |
|
| 2124 data->log_items = g_list_append(data->log_items, set->name); |
|
| 2125 set->name = set->normalized_name = NULL; |
|
| 2126 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2127 } |
2020 } |
| 2128 } |
2021 } |
| 2129 } |
2022 } |
| 2130 |
2023 |
| 2131 static void |
2024 static void |
| 2134 PurpleBlistNode *gnode, *cnode, *bnode; |
2027 PurpleBlistNode *gnode, *cnode, *bnode; |
| 2135 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; |
2028 PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; |
| 2136 gpointer user_data = data->filter_func_user_data; |
2029 gpointer user_data = data->filter_func_user_data; |
| 2137 GHashTable *sets; |
2030 GHashTable *sets; |
| 2138 |
2031 |
| 2139 #ifdef NEW_STYLE_COMPLETION |
|
| 2140 gtk_list_store_clear(data->store); |
2032 gtk_list_store_clear(data->store); |
| 2141 #else |
|
| 2142 GList *item = g_list_append(NULL, NULL); |
|
| 2143 |
|
| 2144 g_list_foreach(data->completion->items, (GFunc)g_free, NULL); |
|
| 2145 g_completion_clear_items(data->completion); |
|
| 2146 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2147 |
2033 |
| 2148 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) |
2034 for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) |
| 2149 { |
2035 { |
| 2150 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) |
2036 if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) |
| 2151 continue; |
2037 continue; |
| 2160 PidginBuddyCompletionEntry entry; |
2046 PidginBuddyCompletionEntry entry; |
| 2161 entry.is_buddy = TRUE; |
2047 entry.is_buddy = TRUE; |
| 2162 entry.entry.buddy = (PurpleBuddy *) bnode; |
2048 entry.entry.buddy = (PurpleBuddy *) bnode; |
| 2163 |
2049 |
| 2164 if (filter_func(&entry, user_data)) { |
2050 if (filter_func(&entry, user_data)) { |
| 2165 #ifdef NEW_STYLE_COMPLETION |
|
| 2166 add_buddyname_autocomplete_entry(data->store, |
2051 add_buddyname_autocomplete_entry(data->store, |
| 2167 ((PurpleContact *)cnode)->alias, |
2052 ((PurpleContact *)cnode)->alias, |
| 2168 purple_buddy_get_contact_alias(entry.entry.buddy), |
2053 purple_buddy_get_contact_alias(entry.entry.buddy), |
| 2169 entry.entry.buddy->account, |
2054 entry.entry.buddy->account, |
| 2170 entry.entry.buddy->name |
2055 entry.entry.buddy->name |
| 2171 ); |
2056 ); |
| 2172 #else |
|
| 2173 item->data = g_strdup(entry.entry.buddy->name); |
|
| 2174 g_completion_add_items(data->completion, item); |
|
| 2175 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2176 } |
2057 } |
| 2177 } |
2058 } |
| 2178 } |
2059 } |
| 2179 } |
2060 } |
| 2180 |
|
| 2181 #ifndef NEW_STYLE_COMPLETION |
|
| 2182 g_list_free(item); |
|
| 2183 data->log_items = NULL; |
|
| 2184 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2185 |
2061 |
| 2186 sets = purple_log_get_log_sets(); |
2062 sets = purple_log_get_log_sets(); |
| 2187 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); |
2063 g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); |
| 2188 g_hash_table_destroy(sets); |
2064 g_hash_table_destroy(sets); |
| 2189 |
2065 |
| 2190 #ifndef NEW_STYLE_COMPLETION |
|
| 2191 g_completion_add_items(data->completion, data->log_items); |
|
| 2192 g_list_free(data->log_items); |
|
| 2193 #endif /* NEW_STYLE_COMPLETION */ |
|
| 2194 } |
2066 } |
| 2195 |
2067 |
| 2196 static void |
2068 static void |
| 2197 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) |
2069 buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) |
| 2198 { |
2070 { |
| 2253 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); |
2124 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); |
| 2254 g_object_unref(store); |
2125 g_object_unref(store); |
| 2255 |
2126 |
| 2256 gtk_entry_completion_set_text_column(completion, 0); |
2127 gtk_entry_completion_set_text_column(completion, 0); |
| 2257 |
2128 |
| 2258 #else /* !NEW_STYLE_COMPLETION */ |
|
| 2259 |
|
| 2260 data = g_new0(PidginCompletionData, 1); |
|
| 2261 |
|
| 2262 data->entry = entry; |
|
| 2263 data->accountopt = accountopt; |
|
| 2264 if (filter_func == NULL) { |
|
| 2265 data->filter_func = pidgin_screenname_autocomplete_default_filter; |
|
| 2266 data->filter_func_user_data = NULL; |
|
| 2267 } else { |
|
| 2268 data->filter_func = filter_func; |
|
| 2269 data->filter_func_user_data = user_data; |
|
| 2270 } |
|
| 2271 data->completion = g_completion_new(NULL); |
|
| 2272 data->completion_started = FALSE; |
|
| 2273 |
|
| 2274 add_completion_list(data); |
|
| 2275 |
|
| 2276 g_completion_set_compare(data->completion, g_ascii_strncasecmp); |
|
| 2277 |
|
| 2278 g_signal_connect(G_OBJECT(entry), "event", |
|
| 2279 G_CALLBACK(completion_entry_event), data); |
|
| 2280 g_signal_connect(G_OBJECT(entry), "destroy", |
|
| 2281 G_CALLBACK(destroy_completion_data), data); |
|
| 2282 |
|
| 2283 #endif /* !NEW_STYLE_COMPLETION */ |
|
| 2284 |
|
| 2285 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, |
2129 purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, |
| 2286 PURPLE_CALLBACK(repopulate_autocomplete), data); |
2130 PURPLE_CALLBACK(repopulate_autocomplete), data); |
| 2287 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, |
2131 purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, |
| 2288 PURPLE_CALLBACK(repopulate_autocomplete), data); |
2132 PURPLE_CALLBACK(repopulate_autocomplete), data); |
| 2289 |
2133 |
| 2348 |
2188 |
| 2349 void (*callback)(const char*,gpointer); |
2189 void (*callback)(const char*,gpointer); |
| 2350 gpointer data; |
2190 gpointer data; |
| 2351 }; |
2191 }; |
| 2352 |
2192 |
| 2353 #if !GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2354 static void |
|
| 2355 icon_filesel_delete_cb(GtkWidget *w, struct _icon_chooser *dialog) |
|
| 2356 { |
|
| 2357 if (dialog->icon_filesel != NULL) |
|
| 2358 gtk_widget_destroy(dialog->icon_filesel); |
|
| 2359 |
|
| 2360 if (dialog->callback) |
|
| 2361 dialog->callback(NULL, dialog->data); |
|
| 2362 |
|
| 2363 g_free(dialog); |
|
| 2364 } |
|
| 2365 #endif /* FILECHOOSER */ |
|
| 2366 |
|
| 2367 |
|
| 2368 |
|
| 2369 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2370 static void |
2193 static void |
| 2371 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog) |
2194 icon_filesel_choose_cb(GtkWidget *widget, gint response, struct _icon_chooser *dialog) |
| 2372 { |
2195 { |
| 2373 char *filename, *current_folder; |
2196 char *filename, *current_folder; |
| 2374 |
2197 |
| 2388 if (current_folder != NULL) { |
2211 if (current_folder != NULL) { |
| 2389 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
2212 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
| 2390 g_free(current_folder); |
2213 g_free(current_folder); |
| 2391 } |
2214 } |
| 2392 |
2215 |
| 2393 #else /* FILECHOOSER */ |
2216 |
| 2394 static void |
|
| 2395 icon_filesel_choose_cb(GtkWidget *w, struct _icon_chooser *dialog) |
|
| 2396 { |
|
| 2397 char *filename, *current_folder; |
|
| 2398 |
|
| 2399 filename = g_strdup(gtk_file_selection_get_filename( |
|
| 2400 GTK_FILE_SELECTION(dialog->icon_filesel))); |
|
| 2401 |
|
| 2402 /* If they typed in a directory, change there */ |
|
| 2403 if (pidgin_check_if_dir(filename, |
|
| 2404 GTK_FILE_SELECTION(dialog->icon_filesel))) |
|
| 2405 { |
|
| 2406 g_free(filename); |
|
| 2407 return; |
|
| 2408 } |
|
| 2409 |
|
| 2410 current_folder = g_path_get_dirname(filename); |
|
| 2411 if (current_folder != NULL) { |
|
| 2412 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", current_folder); |
|
| 2413 g_free(current_folder); |
|
| 2414 } |
|
| 2415 |
|
| 2416 #endif /* FILECHOOSER */ |
|
| 2417 #if 0 /* mismatched curly braces */ |
|
| 2418 } |
|
| 2419 #endif |
|
| 2420 if (dialog->callback) |
2217 if (dialog->callback) |
| 2421 dialog->callback(filename, dialog->data); |
2218 dialog->callback(filename, dialog->data); |
| 2422 gtk_widget_destroy(dialog->icon_filesel); |
2219 gtk_widget_destroy(dialog->icon_filesel); |
| 2423 g_free(filename); |
2220 g_free(filename); |
| 2424 g_free(dialog); |
2221 g_free(dialog); |
| 2425 } |
2222 } |
| 2426 |
2223 |
| 2427 |
2224 |
| 2428 static void |
2225 static void |
| 2429 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2430 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog) |
2226 icon_preview_change_cb(GtkFileChooser *widget, struct _icon_chooser *dialog) |
| 2431 #else /* FILECHOOSER */ |
|
| 2432 icon_preview_change_cb(GtkTreeSelection *sel, struct _icon_chooser *dialog) |
|
| 2433 #endif /* FILECHOOSER */ |
|
| 2434 { |
2227 { |
| 2435 GdkPixbuf *pixbuf, *scale; |
2228 GdkPixbuf *pixbuf, *scale; |
| 2436 int height, width; |
2229 int height, width; |
| 2437 char *basename, *markup, *size; |
2230 char *basename, *markup, *size; |
| 2438 struct stat st; |
2231 struct stat st; |
| 2439 char *filename; |
2232 char *filename; |
| 2440 |
2233 |
| 2441 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2442 filename = gtk_file_chooser_get_preview_filename( |
2234 filename = gtk_file_chooser_get_preview_filename( |
| 2443 GTK_FILE_CHOOSER(dialog->icon_filesel)); |
2235 GTK_FILE_CHOOSER(dialog->icon_filesel)); |
| 2444 #else /* FILECHOOSER */ |
|
| 2445 filename = g_strdup(gtk_file_selection_get_filename( |
|
| 2446 GTK_FILE_SELECTION(dialog->icon_filesel))); |
|
| 2447 #endif /* FILECHOOSER */ |
|
| 2448 |
2236 |
| 2449 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) |
2237 if (!filename || g_stat(filename, &st) || !(pixbuf = gdk_pixbuf_new_from_file(filename, NULL))) |
| 2450 { |
2238 { |
| 2451 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); |
2239 gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->icon_preview), NULL); |
| 2452 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); |
2240 gtk_label_set_markup(GTK_LABEL(dialog->icon_text), ""); |
| 2478 |
2266 |
| 2479 |
2267 |
| 2480 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) { |
2268 GtkWidget *pidgin_buddy_icon_chooser_new(GtkWindow *parent, void(*callback)(const char *, gpointer), gpointer data) { |
| 2481 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1); |
2269 struct _icon_chooser *dialog = g_new0(struct _icon_chooser, 1); |
| 2482 |
2270 |
| 2483 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2484 GtkWidget *vbox; |
2271 GtkWidget *vbox; |
| 2485 #else |
|
| 2486 GtkWidget *hbox; |
|
| 2487 GtkWidget *tv; |
|
| 2488 GtkTreeSelection *sel; |
|
| 2489 #endif /* FILECHOOSER */ |
|
| 2490 const char *current_folder; |
2272 const char *current_folder; |
| 2491 |
2273 |
| 2492 dialog->callback = callback; |
2274 dialog->callback = callback; |
| 2493 dialog->data = data; |
2275 dialog->data = data; |
| 2494 |
2276 |
| 2495 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); |
2277 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); |
| 2496 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ |
|
| 2497 |
2278 |
| 2498 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), |
2279 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), |
| 2499 parent, |
2280 parent, |
| 2500 GTK_FILE_CHOOSER_ACTION_OPEN, |
2281 GTK_FILE_CHOOSER_ACTION_OPEN, |
| 2501 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
2282 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 2522 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview", |
2303 g_signal_connect(G_OBJECT(dialog->icon_filesel), "update-preview", |
| 2523 G_CALLBACK(icon_preview_change_cb), dialog); |
2304 G_CALLBACK(icon_preview_change_cb), dialog); |
| 2524 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response", |
2305 g_signal_connect(G_OBJECT(dialog->icon_filesel), "response", |
| 2525 G_CALLBACK(icon_filesel_choose_cb), dialog); |
2306 G_CALLBACK(icon_filesel_choose_cb), dialog); |
| 2526 icon_preview_change_cb(NULL, dialog); |
2307 icon_preview_change_cb(NULL, dialog); |
| 2527 #else /* FILECHOOSER */ |
|
| 2528 dialog->icon_filesel = gtk_file_selection_new(_("Buddy Icon")); |
|
| 2529 dialog->icon_preview = gtk_image_new(); |
|
| 2530 dialog->icon_text = gtk_label_new(NULL); |
|
| 2531 if ((current_folder != NULL) && (*current_folder != '\0')) |
|
| 2532 gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog->icon_filesel), |
|
| 2533 current_folder); |
|
| 2534 |
|
| 2535 gtk_widget_set_size_request(GTK_WIDGET(dialog->icon_preview),-1, 50); |
|
| 2536 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
|
| 2537 gtk_box_pack_start( |
|
| 2538 GTK_BOX(GTK_FILE_SELECTION(dialog->icon_filesel)->main_vbox), |
|
| 2539 hbox, FALSE, FALSE, 0); |
|
| 2540 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_preview, |
|
| 2541 FALSE, FALSE, 0); |
|
| 2542 gtk_box_pack_end(GTK_BOX(hbox), dialog->icon_text, FALSE, FALSE, 0); |
|
| 2543 |
|
| 2544 tv = GTK_FILE_SELECTION(dialog->icon_filesel)->file_list; |
|
| 2545 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); |
|
| 2546 |
|
| 2547 g_signal_connect(G_OBJECT(sel), "changed", |
|
| 2548 G_CALLBACK(icon_preview_change_cb), dialog); |
|
| 2549 g_signal_connect( |
|
| 2550 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->ok_button), |
|
| 2551 "clicked", |
|
| 2552 G_CALLBACK(icon_filesel_choose_cb), dialog); |
|
| 2553 g_signal_connect( |
|
| 2554 G_OBJECT(GTK_FILE_SELECTION(dialog->icon_filesel)->cancel_button), |
|
| 2555 "clicked", |
|
| 2556 G_CALLBACK(icon_filesel_delete_cb), dialog); |
|
| 2557 g_signal_connect(G_OBJECT(dialog->icon_filesel), "destroy", |
|
| 2558 G_CALLBACK(icon_filesel_delete_cb), dialog); |
|
| 2559 #endif /* FILECHOOSER */ |
|
| 2560 |
2308 |
| 2561 #ifdef _WIN32 |
2309 #ifdef _WIN32 |
| 2562 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show", |
2310 g_signal_connect(G_OBJECT(dialog->icon_filesel), "show", |
| 2563 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel); |
2311 G_CALLBACK(winpidgin_ensure_onscreen), dialog->icon_filesel); |
| 2564 #endif |
2312 #endif |
| 2565 |
2313 |
| 2566 return dialog->icon_filesel; |
2314 return dialog->icon_filesel; |
| 2567 } |
2315 } |
| 2568 |
2316 |
| 2569 |
2317 |
| 2570 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2571 static gboolean |
2318 static gboolean |
| 2572 str_array_match(char **a, char **b) |
2319 str_array_match(char **a, char **b) |
| 2573 { |
2320 { |
| 2574 int i, j; |
2321 int i, j; |
| 2575 |
2322 |
| 2579 for (j = 0; b[j] != NULL; j++) |
2326 for (j = 0; b[j] != NULL; j++) |
| 2580 if (!g_ascii_strcasecmp(a[i], b[j])) |
2327 if (!g_ascii_strcasecmp(a[i], b[j])) |
| 2581 return TRUE; |
2328 return TRUE; |
| 2582 return FALSE; |
2329 return FALSE; |
| 2583 } |
2330 } |
| 2584 #endif |
|
| 2585 |
2331 |
| 2586 gpointer |
2332 gpointer |
| 2587 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) |
2333 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) |
| 2588 { |
2334 { |
| 2589 PurplePluginProtocolInfo *prpl_info; |
2335 PurplePluginProtocolInfo *prpl_info; |
| 2590 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2591 char **prpl_formats; |
2336 char **prpl_formats; |
| 2592 int width, height; |
2337 int width, height; |
| 2593 char **pixbuf_formats = NULL; |
2338 char **pixbuf_formats = NULL; |
| 2594 GdkPixbufFormat *format; |
2339 GdkPixbufFormat *format; |
| 2595 GdkPixbuf *pixbuf; |
2340 GdkPixbuf *pixbuf; |
| 2596 #if !GTK_CHECK_VERSION(2,4,0) |
|
| 2597 GdkPixbufLoader *loader; |
|
| 2598 #endif |
|
| 2599 #endif |
|
| 2600 gchar *contents; |
2341 gchar *contents; |
| 2601 gsize length; |
2342 gsize length; |
| 2602 |
2343 |
| 2603 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); |
2344 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); |
| 2604 |
2345 |
| 2605 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); |
2346 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); |
| 2606 |
2347 |
| 2607 |
2348 |
| 2608 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2609 #if GTK_CHECK_VERSION(2,4,0) |
|
| 2610 format = gdk_pixbuf_get_file_info(path, &width, &height); |
2349 format = gdk_pixbuf_get_file_info(path, &width, &height); |
| 2611 #else |
2350 |
| 2612 loader = gdk_pixbuf_loader_new(); |
|
| 2613 if (g_file_get_contents(path, &contents, &length, NULL)) { |
|
| 2614 gdk_pixbuf_loader_write(loader, contents, length, NULL); |
|
| 2615 g_free(contents); |
|
| 2616 } |
|
| 2617 gdk_pixbuf_loader_close(loader, NULL); |
|
| 2618 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); |
|
| 2619 width = gdk_pixbuf_get_width(pixbuf); |
|
| 2620 height = gdk_pixbuf_get_height(pixbuf); |
|
| 2621 format = gdk_pixbuf_loader_get_format(loader); |
|
| 2622 g_object_unref(G_OBJECT(loader)); |
|
| 2623 #endif |
|
| 2624 if (format == NULL) |
2351 if (format == NULL) |
| 2625 return NULL; |
2352 return NULL; |
| 2626 |
2353 |
| 2627 pixbuf_formats = gdk_pixbuf_format_get_extensions(format); |
2354 pixbuf_formats = gdk_pixbuf_format_get_extensions(format); |
| 2628 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0); |
2355 prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0); |
| 2630 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ |
2357 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ |
| 2631 (prpl_info->icon_spec.min_width <= width && |
2358 (prpl_info->icon_spec.min_width <= width && |
| 2632 prpl_info->icon_spec.max_width >= width && |
2359 prpl_info->icon_spec.max_width >= width && |
| 2633 prpl_info->icon_spec.min_height <= height && |
2360 prpl_info->icon_spec.min_height <= height && |
| 2634 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ |
2361 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ |
| 2635 #endif |
|
| 2636 { |
2362 { |
| 2637 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2638 g_strfreev(prpl_formats); |
2363 g_strfreev(prpl_formats); |
| 2639 g_strfreev(pixbuf_formats); |
2364 g_strfreev(pixbuf_formats); |
| 2640 #endif |
2365 |
| 2641 /* We don't need to scale the image. */ |
2366 /* We don't need to scale the image. */ |
| 2642 |
|
| 2643 contents = NULL; |
2367 contents = NULL; |
| 2644 if (!g_file_get_contents(path, &contents, &length, NULL)) |
2368 if (!g_file_get_contents(path, &contents, &length, NULL)) |
| 2645 { |
2369 { |
| 2646 g_free(contents); |
2370 g_free(contents); |
| 2647 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) |
|
| 2648 g_object_unref(G_OBJECT(pixbuf)); |
|
| 2649 #endif |
|
| 2650 return NULL; |
2371 return NULL; |
| 2651 } |
2372 } |
| 2652 } |
2373 } |
| 2653 #if GTK_CHECK_VERSION(2,2,0) |
|
| 2654 else |
2374 else |
| 2655 { |
2375 { |
| 2656 int i; |
2376 int i; |
| 2657 GError *error = NULL; |
2377 GError *error = NULL; |
| 2658 GdkPixbuf *scale; |
2378 GdkPixbuf *scale; |
| 2769 } |
2489 } |
| 2770 |
2490 |
| 2771 if (len) |
2491 if (len) |
| 2772 *len = length; |
2492 *len = length; |
| 2773 return contents; |
2493 return contents; |
| 2774 #else |
2494 } |
| 2775 /* |
|
| 2776 * The chosen icon wasn't the right size, and we're using |
|
| 2777 * GTK+ 2.0 so we can't scale it. |
|
| 2778 */ |
|
| 2779 return NULL; |
|
| 2780 #endif |
|
| 2781 } |
|
| 2782 |
|
| 2783 #if !GTK_CHECK_VERSION(2,6,0) |
|
| 2784 static void |
|
| 2785 _gdk_file_scale_size_prepared_cb (GdkPixbufLoader *loader, |
|
| 2786 int width, |
|
| 2787 int height, |
|
| 2788 gpointer data) |
|
| 2789 { |
|
| 2790 struct { |
|
| 2791 gint width; |
|
| 2792 gint height; |
|
| 2793 gboolean preserve_aspect_ratio; |
|
| 2794 } *info = data; |
|
| 2795 |
|
| 2796 g_return_if_fail (width > 0 && height > 0); |
|
| 2797 |
|
| 2798 if (info->preserve_aspect_ratio && |
|
| 2799 (info->width > 0 || info->height > 0)) { |
|
| 2800 if (info->width < 0) |
|
| 2801 { |
|
| 2802 width = width * (double)info->height/(double)height; |
|
| 2803 height = info->height; |
|
| 2804 } |
|
| 2805 else if (info->height < 0) |
|
| 2806 { |
|
| 2807 height = height * (double)info->width/(double)width; |
|
| 2808 width = info->width; |
|
| 2809 } |
|
| 2810 else if ((double)height * (double)info->width > |
|
| 2811 (double)width * (double)info->height) { |
|
| 2812 width = 0.5 + (double)width * (double)info->height / (double)height; |
|
| 2813 height = info->height; |
|
| 2814 } else { |
|
| 2815 height = 0.5 + (double)height * (double)info->width / (double)width; |
|
| 2816 width = info->width; |
|
| 2817 } |
|
| 2818 } else { |
|
| 2819 if (info->width > 0) |
|
| 2820 width = info->width; |
|
| 2821 if (info->height > 0) |
|
| 2822 height = info->height; |
|
| 2823 } |
|
| 2824 |
|
| 2825 #if GTK_CHECK_VERSION(2,2,0) /* 2.0 users are going to have very strangely sized things */ |
|
| 2826 gdk_pixbuf_loader_set_size (loader, width, height); |
|
| 2827 #else |
|
| 2828 #warning nosnilmot could not be bothered to fix this properly for you |
|
| 2829 #warning ... good luck ... your images may end up strange sizes |
|
| 2830 #endif |
|
| 2831 } |
|
| 2832 |
|
| 2833 GdkPixbuf * |
|
| 2834 gdk_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, |
|
| 2835 gboolean preserve_aspect_ratio, |
|
| 2836 GError **error) |
|
| 2837 { |
|
| 2838 GdkPixbufLoader *loader; |
|
| 2839 GdkPixbuf *pixbuf; |
|
| 2840 guchar buffer [4096]; |
|
| 2841 int length; |
|
| 2842 FILE *f; |
|
| 2843 struct { |
|
| 2844 gint width; |
|
| 2845 gint height; |
|
| 2846 gboolean preserve_aspect_ratio; |
|
| 2847 } info; |
|
| 2848 GdkPixbufAnimation *animation; |
|
| 2849 GdkPixbufAnimationIter *iter; |
|
| 2850 gboolean has_frame; |
|
| 2851 |
|
| 2852 g_return_val_if_fail (filename != NULL, NULL); |
|
| 2853 g_return_val_if_fail (width > 0 || width == -1, NULL); |
|
| 2854 g_return_val_if_fail (height > 0 || height == -1, NULL); |
|
| 2855 |
|
| 2856 f = g_fopen (filename, "rb"); |
|
| 2857 if (!f) { |
|
| 2858 gint save_errno = errno; |
|
| 2859 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); |
|
| 2860 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (save_errno), |
|
| 2861 _("Failed to open file '%s': %s"), |
|
| 2862 display_name ? display_name : "(unknown)", |
|
| 2863 g_strerror (save_errno)); |
|
| 2864 g_free (display_name); |
|
| 2865 return NULL; |
|
| 2866 } |
|
| 2867 |
|
| 2868 loader = gdk_pixbuf_loader_new (); |
|
| 2869 |
|
| 2870 info.width = width; |
|
| 2871 info.height = height; |
|
| 2872 info.preserve_aspect_ratio = preserve_aspect_ratio; |
|
| 2873 |
|
| 2874 g_signal_connect (loader, "size-prepared", G_CALLBACK (_gdk_file_scale_size_prepared_cb), &info); |
|
| 2875 |
|
| 2876 has_frame = FALSE; |
|
| 2877 while (!has_frame && !feof (f) && !ferror (f)) { |
|
| 2878 length = fread (buffer, 1, sizeof (buffer), f); |
|
| 2879 if (length > 0) |
|
| 2880 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) { |
|
| 2881 gdk_pixbuf_loader_close (loader, NULL); |
|
| 2882 fclose (f); |
|
| 2883 g_object_unref (loader); |
|
| 2884 return NULL; |
|
| 2885 } |
|
| 2886 |
|
| 2887 animation = gdk_pixbuf_loader_get_animation (loader); |
|
| 2888 if (animation) { |
|
| 2889 iter = gdk_pixbuf_animation_get_iter (animation, 0); |
|
| 2890 if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { |
|
| 2891 has_frame = TRUE; |
|
| 2892 } |
|
| 2893 g_object_unref (iter); |
|
| 2894 } |
|
| 2895 } |
|
| 2896 |
|
| 2897 fclose (f); |
|
| 2898 |
|
| 2899 if (!gdk_pixbuf_loader_close (loader, error) && !has_frame) { |
|
| 2900 g_object_unref (loader); |
|
| 2901 return NULL; |
|
| 2902 } |
|
| 2903 |
|
| 2904 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); |
|
| 2905 |
|
| 2906 if (!pixbuf) { |
|
| 2907 gchar *display_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL); |
|
| 2908 g_object_unref (loader); |
|
| 2909 g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, |
|
| 2910 _("Failed to load image '%s': reason not known, probably a corrupt image file"), |
|
| 2911 display_name ? display_name : "(unknown)"); |
|
| 2912 g_free (display_name); |
|
| 2913 return NULL; |
|
| 2914 } |
|
| 2915 |
|
| 2916 g_object_ref (pixbuf); |
|
| 2917 |
|
| 2918 g_object_unref (loader); |
|
| 2919 |
|
| 2920 return pixbuf; |
|
| 2921 } |
|
| 2922 #endif /* ! Gtk 2.6.0 */ |
|
| 2923 |
2495 |
| 2924 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) |
2496 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) |
| 2925 { |
2497 { |
| 2926 PurpleBuddy *buddy; |
2498 PurpleBuddy *buddy; |
| 2927 PurpleContact *contact; |
2499 PurpleContact *contact; |
| 2951 return ret; |
2523 return ret; |
| 2952 } |
2524 } |
| 2953 |
2525 |
| 2954 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) |
2526 void pidgin_set_urgent(GtkWindow *window, gboolean urgent) |
| 2955 { |
2527 { |
| 2956 #if GTK_CHECK_VERSION(2,8,0) |
|
| 2957 gtk_window_set_urgency_hint(window, urgent); |
2528 gtk_window_set_urgency_hint(window, urgent); |
| 2958 #elif defined _WIN32 |
2529 #if defined _WIN32 |
| 2959 winpidgin_window_flash(window, urgent); |
2530 winpidgin_window_flash(window, urgent); |
| 2960 #elif defined GDK_WINDOWING_X11 |
|
| 2961 GdkWindow *gdkwin; |
|
| 2962 XWMHints *hints; |
|
| 2963 |
|
| 2964 g_return_if_fail(window != NULL); |
|
| 2965 |
|
| 2966 gdkwin = GTK_WIDGET(window)->window; |
|
| 2967 |
|
| 2968 g_return_if_fail(gdkwin != NULL); |
|
| 2969 |
|
| 2970 hints = XGetWMHints(GDK_WINDOW_XDISPLAY(gdkwin), |
|
| 2971 GDK_WINDOW_XWINDOW(gdkwin)); |
|
| 2972 if(!hints) |
|
| 2973 hints = XAllocWMHints(); |
|
| 2974 |
|
| 2975 if (urgent) |
|
| 2976 hints->flags |= XUrgencyHint; |
|
| 2977 else |
|
| 2978 hints->flags &= ~XUrgencyHint; |
|
| 2979 XSetWMHints(GDK_WINDOW_XDISPLAY(gdkwin), |
|
| 2980 GDK_WINDOW_XWINDOW(gdkwin), hints); |
|
| 2981 XFree(hints); |
|
| 2982 #else |
|
| 2983 /* do something else? */ |
|
| 2984 #endif |
2531 #endif |
| 2985 } |
2532 } |
| 2986 |
2533 |
| 2987 static GSList *minidialogs = NULL; |
2534 static GSList *minidialogs = NULL; |
| 2988 |
2535 |
| 3287 style->text_aa[GTK_STATE_NORMAL].green >> 8, |
2834 style->text_aa[GTK_STATE_NORMAL].green >> 8, |
| 3288 style->text_aa[GTK_STATE_NORMAL].blue >> 8); |
2835 style->text_aa[GTK_STATE_NORMAL].blue >> 8); |
| 3289 return dim_grey_string; |
2836 return dim_grey_string; |
| 3290 } |
2837 } |
| 3291 |
2838 |
| 3292 #if !GTK_CHECK_VERSION(2,2,0) |
|
| 3293 GtkTreePath * |
|
| 3294 gtk_tree_path_new_from_indices (gint first_index, ...) |
|
| 3295 { |
|
| 3296 int arg; |
|
| 3297 va_list args; |
|
| 3298 GtkTreePath *path; |
|
| 3299 |
|
| 3300 path = gtk_tree_path_new (); |
|
| 3301 |
|
| 3302 va_start (args, first_index); |
|
| 3303 arg = first_index; |
|
| 3304 |
|
| 3305 while (arg != -1) |
|
| 3306 { |
|
| 3307 gtk_tree_path_append_index (path, arg); |
|
| 3308 arg = va_arg (args, gint); |
|
| 3309 } |
|
| 3310 |
|
| 3311 va_end (args); |
|
| 3312 |
|
| 3313 return path; |
|
| 3314 } |
|
| 3315 #endif |
|
| 3316 |
|
| 3317 static void |
2839 static void |
| 3318 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) |
2840 combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) |
| 3319 { |
2841 { |
| 3320 char *text = gtk_combo_box_get_active_text(combo_box); |
2842 char *text = gtk_combo_box_get_active_text(combo_box); |
| 3321 gtk_entry_set_text(entry, text ? text : ""); |
2843 gtk_entry_set_text(entry, text ? text : ""); |
| 3697 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3217 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3698 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
3218 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
| 3699 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3219 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3700 |
3220 |
| 3701 /* Open Containing Directory */ |
3221 /* Open Containing Directory */ |
| 3702 #if GTK_CHECK_VERSION(2,6,0) |
|
| 3703 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); |
3222 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); |
| 3704 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
3223 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
| 3705 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3224 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3706 #else |
3225 |
| 3707 item = gtk_menu_item_new_with_mnemonic(_("Open _Containing Directory")); |
|
| 3708 #endif |
|
| 3709 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); |
3226 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); |
| 3710 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3227 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3711 |
3228 |
| 3712 return TRUE; |
3229 return TRUE; |
| 3713 } |
3230 } |
| 3769 return TRUE; |
3286 return TRUE; |
| 3770 |
3287 |
| 3771 url = gtk_imhtml_link_get_url(link); |
3288 url = gtk_imhtml_link_get_url(link); |
| 3772 |
3289 |
| 3773 /* Play Sound */ |
3290 /* Play Sound */ |
| 3774 #if GTK_CHECK_VERSION(2,6,0) |
|
| 3775 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); |
3291 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); |
| 3776 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); |
3292 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); |
| 3777 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
3293 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
| 3778 #else |
3294 |
| 3779 item = gtk_menu_item_new_with_mnemonic(_("_Play Sound")); |
|
| 3780 #endif |
|
| 3781 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
3295 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); |
| 3782 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
3296 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
| 3783 |
3297 |
| 3784 /* Save File */ |
3298 /* Save File */ |
| 3785 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); |
3299 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); |