/* * fm-file-launcher.c * * Copyright 2009 - 2010 Hong Jen Yee (PCMan) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "fm-file-launcher.h" #include "fm-file-info-job.h" static void launch_files(GAppLaunchContext* ctx, GAppInfo* app, GList* file_infos) { } gboolean fm_launch_desktop_entry(GAppLaunchContext* ctx, const char* file_or_id, GList* uris, GError** err) { GKeyFile* kf = g_key_file_new(); gboolean loaded; gboolean ret = FALSE; if(g_path_is_absolute(file_or_id)) loaded = g_key_file_load_from_file(kf, file_or_id, 0, err); else { char* tmp = g_strconcat("applications/", file_or_id, NULL); loaded = g_key_file_load_from_data_dirs(kf, tmp, NULL, 0, err); g_free(tmp); } if(loaded) { GList* _uris = NULL; GAppInfo* app = NULL; char* type = g_key_file_get_string(kf, G_KEY_FILE_DESKTOP_GROUP, "Type", NULL); if(type) { if(strcmp(type, "Application") == 0) app = g_desktop_app_info_new_from_keyfile(kf); else if(strcmp(type, "Link") == 0) { char* url = g_key_file_get_string(kf, G_KEY_FILE_DESKTOP_GROUP, "URL", NULL); if(url) { char* scheme = g_uri_parse_scheme(url); if(scheme) { /* Damn! this actually relies on gconf to work. */ /* FIXME: use our own way to get a usable browser later. */ app = g_app_info_get_default_for_uri_scheme(scheme); uris = _uris = g_list_prepend(NULL, url); g_free(scheme); } } } else if(strcmp(type, "Directory") == 0) { /* FIXME: how should this work? It's not defined in the spec. */ } if(app) ret = g_app_info_launch_uris(app, uris, ctx, err); } } g_key_file_free(kf); return ret; } 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_launch_paths(GAppLaunchContext* ctx, GList* paths, FmFileLauncher* launcher, gpointer user_data) { FmJob* job = fm_file_info_job_new(NULL, 0); GList* l; gboolean ret; for(l=paths;l;l=l->next) fm_file_info_job_add(FM_FILE_INFO_JOB(job), (FmPath*)l->data); ret = fm_job_run_sync_with_mainloop(job); if(ret) { GList* file_infos = fm_list_peek_head_link(FM_FILE_INFO_JOB(job)->file_infos); if(file_infos) ret = fm_launch_files(ctx, file_infos, launcher, user_data); else ret = FALSE; } g_object_unref(job); return ret; }