pidgin/gtkrequest.c

changeset 42352
1c53950f9052
parent 42269
fa7ab9df882b
child 42360
f08d93308aa4
equal deleted inserted replaced
42351:876522a8b982 42352:1c53950f9052
38 typedef struct 38 typedef struct
39 { 39 {
40 PurpleRequestType type; 40 PurpleRequestType type;
41 41
42 void *user_data; 42 void *user_data;
43 /* May be GtkWidget or GtkNativeDialog */ 43 /* May be GtkWidget or GtkFileDialog. */
44 gpointer dialog; 44 gpointer dialog;
45 GCancellable *cancellable;
45 46
46 GtkWidget *ok_button; 47 GtkWidget *ok_button;
47 48
48 size_t cb_count; 49 size_t cb_count;
49 GCallback *cbs; 50 GCallback *cbs;
2000 2001
2001 return data; 2002 return data;
2002 } 2003 }
2003 2004
2004 static void 2005 static void
2005 pidgin_request_file_folder_response_cb(G_GNUC_UNUSED GtkWidget *widget, 2006 pidgin_request_file_response_cb(GObject *obj, GAsyncResult *result,
2006 gint response, PidginRequestData *data) 2007 gpointer user_data)
2007 { 2008 {
2008 GFile *current_path; 2009 PidginRequestData *data = user_data;
2009 2010 GFile *path = NULL;
2010 if (response != GTK_RESPONSE_ACCEPT) { 2011 GFile *parent = NULL;
2011 if (data->cbs[0] != NULL) 2012 GError *error = NULL;
2012 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, NULL); 2013
2013 purple_request_close(data->type, data); 2014 if(data->u.file.savedialog) {
2015 path = gtk_file_dialog_save_finish(GTK_FILE_DIALOG(obj), result,
2016 &error);
2017 } else {
2018 path = gtk_file_dialog_open_finish(GTK_FILE_DIALOG(obj), result,
2019 &error);
2020 }
2021 if(path == NULL) {
2022 if(!g_error_matches(error, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_CANCELLED)) {
2023 if(data->cbs[0] != NULL) {
2024 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, NULL);
2025 }
2026 purple_request_close(data->type, data);
2027 }
2028 g_clear_error(&error);
2014 return; 2029 return;
2015 } 2030 }
2016 2031
2017 current_path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->dialog)); 2032 parent = g_file_get_parent(path);
2018 if (current_path != NULL) { 2033 if(parent != NULL) {
2019 gchar *current_folder = g_file_get_path(current_path); 2034 char *current_folder = g_file_get_path(parent);
2020 if (data->u.file.savedialog) { 2035 if (data->u.file.savedialog) {
2021 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_save_folder", current_folder); 2036 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_save_folder",
2037 current_folder);
2022 } else { 2038 } else {
2023 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder", current_folder); 2039 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder",
2040 current_folder);
2024 } 2041 }
2025 g_free(current_folder); 2042 g_free(current_folder);
2026 } 2043 }
2027 if (data->cbs[1] != NULL) { 2044
2028 GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(data->dialog)); 2045 if(data->cbs[1] != NULL) {
2029 char *filename = g_file_get_path(file); 2046 char *filename = g_file_get_path(path);
2030 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, filename); 2047 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, filename);
2031 g_free(filename); 2048 g_free(filename);
2032 g_object_unref(file); 2049 }
2033 } 2050
2051 g_clear_object(&parent);
2052 g_clear_object(&path);
2053 g_clear_object(&data->cancellable);
2034 purple_request_close(data->type, data); 2054 purple_request_close(data->type, data);
2035 2055 }
2036 g_clear_object(&current_path); 2056
2057 static void
2058 pidgin_request_folder_response_cb(GObject *obj, GAsyncResult *result,
2059 gpointer user_data)
2060 {
2061 PidginRequestData *data = user_data;
2062 GFile *path = NULL;
2063 char *folder = NULL;
2064 GError *error = NULL;
2065
2066 path = gtk_file_dialog_select_folder_finish(GTK_FILE_DIALOG(obj), result,
2067 &error);
2068 if(path == NULL) {
2069 if(!g_error_matches(error, GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_CANCELLED)) {
2070 if(data->cbs[0] != NULL) {
2071 ((PurpleRequestFileCb)data->cbs[0])(data->user_data, NULL);
2072 }
2073 purple_request_close(data->type, data);
2074 }
2075 g_clear_error(&error);
2076 return;
2077 }
2078
2079 folder = g_file_get_path(path);
2080 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder",
2081 folder);
2082
2083 if(data->cbs[1] != NULL) {
2084 ((PurpleRequestFileCb)data->cbs[1])(data->user_data, folder);
2085 }
2086
2087 g_free(folder);
2088 g_clear_object(&path);
2089 g_clear_object(&data->cancellable);
2090 purple_request_close(data->type, data);
2037 } 2091 }
2038 2092
2039 static void * 2093 static void *
2040 pidgin_request_file(const char *title, const char *filename, 2094 pidgin_request_file(const char *title, const char *filename,
2041 gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, 2095 gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
2042 G_GNUC_UNUSED PurpleRequestCommonParameters *cpar, 2096 G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
2043 gpointer user_data) 2097 gpointer user_data)
2044 { 2098 {
2045 PidginRequestData *data; 2099 PidginRequestData *data;
2046 GtkFileChooserNative *filesel; 2100 GtkFileDialog *dialog = NULL;
2047 #ifdef _WIN32 2101 #ifdef _WIN32
2048 GFile *file = NULL;
2049 const gchar *current_folder; 2102 const gchar *current_folder;
2050 gboolean folder_set = FALSE; 2103 gboolean folder_set = FALSE;
2051 #endif 2104 #endif
2052 2105
2053 data = g_new0(PidginRequestData, 1); 2106 data = g_new0(PidginRequestData, 1);
2057 data->cbs = g_new0(GCallback, 2); 2110 data->cbs = g_new0(GCallback, 2);
2058 data->cbs[0] = cancel_cb; 2111 data->cbs[0] = cancel_cb;
2059 data->cbs[1] = ok_cb; 2112 data->cbs[1] = ok_cb;
2060 data->u.file.savedialog = savedialog; 2113 data->u.file.savedialog = savedialog;
2061 2114
2062 filesel = gtk_file_chooser_native_new( 2115 data->dialog = dialog = gtk_file_dialog_new();
2063 title ? title 2116 gtk_file_dialog_set_title(dialog,
2064 : (savedialog ? _("Save File...") : _("Open File...")), 2117 title ? title
2065 NULL, 2118 : (savedialog ? _("Save File...")
2066 savedialog ? GTK_FILE_CHOOSER_ACTION_SAVE 2119 : _("Open File...")));
2067 : GTK_FILE_CHOOSER_ACTION_OPEN, 2120
2068 savedialog ? _("_Save") : _("_Open"), _("_Cancel")); 2121 if(!purple_strempty(filename)) {
2069
2070 if ((filename != NULL) && (*filename != '\0')) {
2071 GFile *path = g_file_new_for_path(filename); 2122 GFile *path = g_file_new_for_path(filename);
2072 2123
2073 if(savedialog) { 2124 if(savedialog || g_file_test(filename, G_FILE_TEST_EXISTS)) {
2074 gtk_file_chooser_set_file(GTK_FILE_CHOOSER(filesel), path, NULL); 2125 gtk_file_dialog_set_initial_file(dialog, path);
2075 } else if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
2076 gtk_file_chooser_set_file(GTK_FILE_CHOOSER(filesel), path, NULL);
2077 } 2126 }
2078 2127
2079 g_object_unref(path); 2128 g_object_unref(path);
2080 } 2129 }
2081 2130
2084 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_save_folder"); 2133 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_save_folder");
2085 } else { 2134 } else {
2086 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder"); 2135 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder");
2087 } 2136 }
2088 2137
2089 if ((filename == NULL || *filename == '\0' || !g_file_test(filename, G_FILE_TEST_EXISTS)) && 2138 if((purple_strempty(filename) || !g_file_test(filename, G_FILE_TEST_EXISTS)) &&
2090 (current_folder != NULL) && (*current_folder != '\0')) 2139 !purple_strempty(current_folder))
2091 { 2140 {
2092 file = g_file_new_for_path(current_folder); 2141 GFile *file = g_file_new_for_path(current_folder);
2093 folder_set = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel), file, NULL); 2142 gtk_file_dialog_set_initial_folder(dialog, file, NULL);
2094 } 2143 folder_set = TRUE;
2095 2144 g_clear_object(&file);
2096 if (!folder_set && (filename == NULL || *filename == '\0' || !g_file_test(filename, G_FILE_TEST_EXISTS))) { 2145 }
2146
2147 if(!folder_set &&
2148 (purple_strempty(filename) || !g_file_test(filename, G_FILE_TEST_EXISTS)))
2149 {
2097 char *my_documents = wpurple_get_special_folder(CSIDL_PERSONAL); 2150 char *my_documents = wpurple_get_special_folder(CSIDL_PERSONAL);
2098 2151
2099 g_clear_object(&file);
2100
2101 if (my_documents != NULL) { 2152 if (my_documents != NULL) {
2102 file = g_file_new_for_path(my_documents); 2153 GFile *file = g_file_new_for_path(my_documents);
2103 gtk_file_chooser_set_current_folder( 2154
2104 GTK_FILE_CHOOSER(filesel), file, NULL); 2155 gtk_file_dialog_set_initial_folder(dialog, file);
2105 2156
2106 g_free(my_documents); 2157 g_free(my_documents);
2107 } 2158 g_clear_object(&file);
2108 } 2159 }
2109 2160 }
2110 g_clear_object(&file);
2111 #endif 2161 #endif
2112 2162
2113 g_signal_connect(G_OBJECT(filesel), "response", 2163 data->cancellable = g_cancellable_new();
2114 G_CALLBACK(pidgin_request_file_folder_response_cb), data); 2164 if(savedialog) {
2115 2165 gtk_file_dialog_save(dialog, NULL, data->cancellable,
2116 #if 0 2166 pidgin_request_file_response_cb, data);
2117 /* FIXME: Not implemented for native dialogs. */ 2167 } else {
2118 pidgin_auto_parent_window(filesel); 2168 gtk_file_dialog_open(dialog, NULL, data->cancellable,
2119 #endif 2169 pidgin_request_file_response_cb, data);
2120 2170 }
2121 data->dialog = filesel;
2122 gtk_native_dialog_show(GTK_NATIVE_DIALOG(filesel));
2123 2171
2124 return (void *)data; 2172 return (void *)data;
2125 } 2173 }
2126 2174
2127 static void * 2175 static void *
2129 GCallback cancel_cb, 2177 GCallback cancel_cb,
2130 G_GNUC_UNUSED PurpleRequestCommonParameters *cpar, 2178 G_GNUC_UNUSED PurpleRequestCommonParameters *cpar,
2131 gpointer user_data) 2179 gpointer user_data)
2132 { 2180 {
2133 PidginRequestData *data; 2181 PidginRequestData *data;
2134 GtkFileChooserNative *dirsel; 2182 GtkFileDialog *dialog = NULL;
2135 2183
2136 data = g_new0(PidginRequestData, 1); 2184 data = g_new0(PidginRequestData, 1);
2137 data->type = PURPLE_REQUEST_FOLDER; 2185 data->type = PURPLE_REQUEST_FOLDER;
2138 data->user_data = user_data; 2186 data->user_data = user_data;
2139 data->cb_count = 2; 2187 data->cb_count = 2;
2140 data->cbs = g_new0(GCallback, 2); 2188 data->cbs = g_new0(GCallback, 2);
2141 data->cbs[0] = cancel_cb; 2189 data->cbs[0] = cancel_cb;
2142 data->cbs[1] = ok_cb; 2190 data->cbs[1] = ok_cb;
2143 data->u.file.savedialog = FALSE; 2191 data->u.file.savedialog = FALSE;
2144 2192
2145 dirsel = gtk_file_chooser_native_new( 2193 data->cancellable = g_cancellable_new();
2146 title ? title : _("Select Folder..."), NULL, 2194 data->dialog = dialog = gtk_file_dialog_new();
2147 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, _("_OK"), _("_Cancel")); 2195 gtk_file_dialog_set_title(dialog, title ? title : _("Select Folder..."));
2148 2196
2149 if ((dirname != NULL) && (*dirname != '\0')) { 2197 if(!purple_strempty(dirname)) {
2150 GFile *path = g_file_new_for_path(dirname); 2198 GFile *path = g_file_new_for_path(dirname);
2151 2199 gtk_file_dialog_set_initial_folder(dialog, path);
2152 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dirsel), path,
2153 NULL);
2154
2155 g_object_unref(path); 2200 g_object_unref(path);
2156 } 2201 }
2157 2202
2158 g_signal_connect(G_OBJECT(dirsel), "response", 2203 gtk_file_dialog_select_folder(dialog, NULL, data->cancellable,
2159 G_CALLBACK(pidgin_request_file_folder_response_cb), data); 2204 pidgin_request_folder_response_cb, data);
2160
2161 data->dialog = dirsel;
2162 #if 0
2163 /* FIXME: Not implemented for native dialogs. */
2164 pidgin_auto_parent_window(dirsel);
2165 #endif
2166
2167 gtk_native_dialog_show(GTK_NATIVE_DIALOG(dirsel));
2168 2205
2169 return (void *)data; 2206 return (void *)data;
2170 } 2207 }
2171 2208
2172 /* if request callback issues another request, it should be attached to the 2209 /* if request callback issues another request, it should be attached to the
2200 static void 2237 static void
2201 pidgin_close_request(PurpleRequestType type, void *ui_handle) 2238 pidgin_close_request(PurpleRequestType type, void *ui_handle)
2202 { 2239 {
2203 PidginRequestData *data = (PidginRequestData *)ui_handle; 2240 PidginRequestData *data = (PidginRequestData *)ui_handle;
2204 2241
2205 g_free(data->cbs); 2242 if(data->cancellable != NULL) {
2243 g_cancellable_cancel(data->cancellable);
2244 }
2206 2245
2207 if (type == PURPLE_REQUEST_FILE || type == PURPLE_REQUEST_FOLDER) { 2246 if (type == PURPLE_REQUEST_FILE || type == PURPLE_REQUEST_FOLDER) {
2208 /* Will be a GtkNativeDialog, not GtkDialog. */ 2247 /* Will be a GtkFileDialog, not GtkDialog. */
2209 g_object_unref(data->dialog); 2248 g_clear_object(&data->dialog);
2210 } else { 2249 } else {
2211 pidgin_window_detach_children(GTK_WINDOW(data->dialog)); 2250 pidgin_window_detach_children(GTK_WINDOW(data->dialog));
2212 2251
2213 gtk_window_destroy(GTK_WINDOW(data->dialog)); 2252 gtk_window_destroy(GTK_WINDOW(data->dialog));
2214 } 2253 }
2215 2254
2216 if(type == PURPLE_REQUEST_FIELDS) { 2255 if(type == PURPLE_REQUEST_FIELDS) {
2217 g_clear_object(&data->u.multifield.page); 2256 g_clear_object(&data->u.multifield.page);
2218 } 2257 }
2219 2258
2259 g_clear_object(&data->cancellable);
2260 g_free(data->cbs);
2220 g_free(data); 2261 g_free(data);
2221 } 2262 }
2222 2263
2223 GtkWindow * 2264 GtkWindow *
2224 pidgin_request_get_dialog_window(void *ui_handle) 2265 pidgin_request_get_dialog_window(void *ui_handle)
2228 g_return_val_if_fail( 2269 g_return_val_if_fail(
2229 purple_request_is_valid_ui_handle(data, NULL), NULL); 2270 purple_request_is_valid_ui_handle(data, NULL), NULL);
2230 2271
2231 if (data->type == PURPLE_REQUEST_FILE || 2272 if (data->type == PURPLE_REQUEST_FILE ||
2232 data->type == PURPLE_REQUEST_FOLDER) { 2273 data->type == PURPLE_REQUEST_FOLDER) {
2233 /* Not a GtkWidget, but a GtkFileChooserNative. Eventually this function 2274 /* Not a GtkWidget, but a GtkFileDialog. Eventually this function
2234 * should not be needed, once we don't need to auto-parent. */ 2275 * should not be needed, once we don't need to auto-parent. */
2235 return NULL; 2276 return NULL;
2236 } 2277 }
2237 2278
2238 return GTK_WINDOW(data->dialog); 2279 return GTK_WINDOW(data->dialog);

mercurial