gboolean fm_launch_files(GAppLaunchContext* ctx, GList* file_infos, FmFileLauncher* launcher, gpointer user_data) { GList* l; GHashTable* hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); GList* folders = NULL; FmFileInfo* fi; GError* err = NULL; GAppInfo* app; for(l = file_infos; l; l=l->next) { GList* fis; fi = (FmFileInfo*)l->data; if(fm_file_info_is_dir(fi)) folders = g_list_prepend(folders, fi); else { /* FIXME: handle shortcuts, such as the items in menu:// */ if(fm_path_is_native(fi->path)) { char* filename; if(fm_file_info_is_desktop_entry(fi)) { /* if it's a desktop entry file, directly launch it. */ filename = fm_path_to_str(fi->path); if(!fm_launch_desktop_entry(ctx, filename, NULL, &err)) { if(launcher->error) launcher->error(ctx, err, user_data); g_error_free(err); err = NULL; } continue; } else if(fm_file_info_is_executable_type(fi)) { /* if it's an executable file, directly execute it. */ filename = fm_path_to_str(fi->path); /* FIXME: we need to use eaccess/euidaccess here. */ if(g_file_test(filename, G_FILE_TEST_IS_EXECUTABLE)) { app = g_app_info_create_from_commandline(filename, NULL, 0, NULL); if(app) { if(!g_app_info_launch(app, NULL, ctx, &err)) { if(launcher->error) launcher->error(ctx, err, user_data); g_error_free(err); err = NULL; } g_object_unref(app); continue; } } g_free(filename); } } else /* not a native path */ { if(fm_file_info_is_shortcut(fi) && !fm_file_info_is_dir(fi)) { /* FIXME: special handling for shortcuts */ if(fm_path_is_xdg_menu(fi->path) && fi->target) { if(!fm_launch_desktop_entry(ctx, fi->target, NULL, &err)) { if(launcher->error) launcher->error(ctx, err, user_data); g_error_free(err); err = NULL; } continue; } } } if(fi->type && fi->type->type) { fis = g_hash_table_lookup(hash, fi->type->type); fis = g_list_prepend(fis, fi); g_hash_table_insert(hash, fi->type->type, fis); } } } if(g_hash_table_size(hash) > 0) { GHashTableIter it; const char* type; GList* fis; g_hash_table_iter_init(&it, hash); while(g_hash_table_iter_next(&it, &type, &fis)) { GAppInfo* app = g_app_info_get_default_for_type(type, FALSE); if(!app) { if(launcher->get_app) { FmMimeType* mime_type = ((FmFileInfo*)fis->data)->type; app = launcher->get_app(fis, mime_type, user_data, NULL); } } if(app) { for(l=fis; l; l=l->next) { char* uri; fi = (FmFileInfo*)l->data; uri = fm_path_to_uri(fi->path); l->data = uri; } fis = g_list_reverse(fis); g_app_info_launch_uris(app, fis, ctx, err); /* free URI strings */ g_list_foreach(fis, (GFunc)g_free, NULL); g_object_unref(app); } g_list_free(fis); } } g_hash_table_destroy(hash); if(folders) { folders = g_list_reverse(folders); if(launcher->open_folder) { launcher->open_folder(ctx, folders, user_data, &err); if(err) { if(launcher->error) launcher->error(ctx, err, user_data); g_error_free(err); err = NULL; } } g_list_free(folders); } return TRUE; }
/********************************************************************* * ... * * ********************************************************************/ gboolean fm_file_info_job_run (FmJob *fmjob) { FmFileInfoJob *job = (FmFileInfoJob*) fmjob; GError *err = NULL; GList *l; for (l = fm_list_peek_head_link (job->file_infos); !fm_job_is_cancelled (fmjob) && l; ) { FmFileInfo *file_info = (FmFileInfo*) l->data; GList *next = l->next; job->current = file_info->path; if (fm_path_is_native (file_info->path)) { char *path_str = fm_path_to_str (file_info->path); // FileInfo rework: new function for testing... // this one is not cancellable and doesn't handle errors... // if (!fm_file_info_job_get_info_for_native_file (FM_JOB (job), file_info, path_str, &err)) if (!fm_file_info_set_for_native_file (file_info, path_str)) { //~ FmJobErrorAction act = fm_job_emit_error (FM_JOB(job), err, FM_JOB_ERROR_MILD); //~ //~ g_error_free (err); //~ err = NULL; //~ //~ if (act == FM_JOB_RETRY) //~ continue; DEBUG ("fm_file_info_set_for_native_file: error reading %s\n", path_str); next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_free (path_str); } else { GFile *gf; if (fm_path_is_virtual (file_info->path)) { // This is a xdg menu if (fm_path_is_xdg_menu (file_info->path)) { MenuCache *mc; MenuCacheDir *dir; char *path_str = fm_path_to_str (file_info->path); char *menu_name = path_str + 5, ch; char *dir_name; while (*menu_name == '/') ++menu_name; dir_name = menu_name; while (*dir_name && *dir_name != '/') ++dir_name; ch = *dir_name; *dir_name = '\0'; menu_name = g_strconcat (menu_name, ".menu", NULL); mc = menu_cache_lookup_sync (menu_name); g_free (menu_name); if (*dir_name && !(*dir_name == '/' && dir_name[1] == '\0')) { char *tmp = g_strconcat ("/", menu_cache_item_get_id (MENU_CACHE_ITEM(menu_cache_get_root_dir (mc))), dir_name, NULL); dir = menu_cache_get_dir_from_path (mc, tmp); g_free (tmp); } else { dir = menu_cache_get_root_dir (mc); } if (dir) { fm_file_info_set_from_menu_cache_item (file_info, (MenuCacheItem*) dir); } else { next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_free (path_str); menu_cache_unref (mc); l = l->next; continue; } } gf = fm_path_to_gfile (file_info->path); if (!fm_file_info_job_get_info_for_gfile (FM_JOB (job), file_info, gf, &err)) { FmJobErrorAction act = fm_job_emit_error (FM_JOB (job), err, FM_JOB_ERROR_MILD); g_error_free (err); err = NULL; if (act == FM_JOB_RETRY) continue; next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_object_unref (gf); } l = next; } return TRUE; }