static void test_parsing(FmPathFunc func, const char* str, const char** expected, int n_expected) { GSList* elements = NULL, *l; int i; FmPath *path, *element; g_print("\ntry to parse \'%s\':\n[", str); path = func(str); for(element = path; element; element = fm_path_get_parent(element)) elements = g_slist_prepend(elements, element); for(i = 0, l = elements; l; l=l->next, ++i) { g_assert_cmpint(i, <, n_expected); element = (FmPath*)l->data; g_print("\'%s\'", fm_path_get_basename(element)); if(l->next) g_print(", "); g_assert_cmpstr(fm_path_get_basename(element), ==, expected[i]); } g_slist_free(elements); g_print("]\n"); g_assert_cmpint(i, ==, n_expected); fm_path_unref(path); }
static void on_browse_btn_clicked(GtkButton* btn, AppChooserData* data) { FmPath* file; GtkFileFilter* filter = gtk_file_filter_new(); char* binary; gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME|GTK_FILE_FILTER_MIME_TYPE, exec_filter_func, NULL, NULL); /* gtk_file_filter_set_name(filter, _("Executable files")); */ file = fm_select_file(GTK_WINDOW(data->dlg), NULL, "/usr/bin", TRUE, FALSE, filter, NULL); if (file == NULL) return; binary = fm_path_to_str(file); if (g_str_has_suffix(fm_path_get_basename(file), ".desktop")) { GKeyFile *kf = g_key_file_new(); GDesktopAppInfo *info; if (g_key_file_load_from_file(kf, binary, 0, NULL) && (info = g_desktop_app_info_new_from_keyfile(kf)) != NULL) /* it is a valid desktop entry */ { /* FIXME: it will duplicate the file, how to avoid that? */ gtk_entry_set_text(data->cmdline, g_app_info_get_commandline(G_APP_INFO(info))); gtk_entry_set_text(data->app_name, g_app_info_get_name(G_APP_INFO(info))); gtk_toggle_button_set_active(data->use_terminal, g_key_file_get_boolean(kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TERMINAL, NULL)); gtk_toggle_button_set_active(data->keep_open, g_key_file_get_boolean(kf, G_KEY_FILE_DESKTOP_GROUP, "X-KeepTerminal", NULL)); g_object_unref(info); g_key_file_free(kf); fm_path_unref(file); return; } g_key_file_free(kf); } gtk_entry_set_text(data->cmdline, binary); g_free(binary); fm_path_unref(file); }
void renameFile(FmFileInfo *file, QWidget *parent) { FmPath* path = fm_file_info_get_path(file); FilenameDialog dlg(parent); dlg.setWindowTitle(QObject::tr("Rename File")); dlg.setLabelText(QObject::tr("Please enter a new name:")); // FIXME: what's the best way to handle non-UTF8 filename encoding here? QString old_name = QString::fromLocal8Bit(fm_path_get_basename(path)); dlg.setTextValue(old_name); if(fm_file_info_is_dir(file)) // select filename extension for directories dlg.setSelectExtension(true); if(dlg.exec() != QDialog::Accepted) return; QString new_name = dlg.textValue(); if(new_name == old_name) return; GFile* gf = fm_path_to_gfile(path); GFile* parent_gf = g_file_get_parent(gf); GFile* dest = g_file_get_child(G_FILE(parent_gf), new_name.toLocal8Bit().data()); g_object_unref(parent_gf); GError* err = NULL; if(!g_file_move(gf, dest, GFileCopyFlags(G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NO_FALLBACK_FOR_MOVE | G_FILE_COPY_NOFOLLOW_SYMLINKS), NULL, /* make this cancellable later. */ NULL, NULL, &err)) { QMessageBox::critical(parent, QObject::tr("Error"), err->message); g_error_free(err); } g_object_unref(dest); g_object_unref(gf); }
static gboolean fm_file_info_job_run(FmJob* fmjob) { GList* l; FmFileInfoJob* job = (FmFileInfoJob*)fmjob; GError* err = NULL; if(job->file_infos == NULL) return FALSE; for(l = fm_file_info_list_peek_head_link(job->file_infos); !fm_job_is_cancelled(fmjob) && l;) { FmFileInfo* fi = (FmFileInfo*)l->data; GList* next = l->next; FmPath* path = fm_file_info_get_path(fi); if(job->current) fm_path_unref(job->current); job->current = fm_path_ref(path); if(fm_path_is_native(path)) { char* path_str = fm_path_to_str(path); if(!_fm_file_info_job_get_info_for_native_file(fmjob, fi, path_str, &err)) { FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD); g_error_free(err); err = NULL; if(act == FM_JOB_RETRY) { g_free(path_str); continue; /* retry */ } fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */ } else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE)) fm_job_call_main_thread(fmjob, _emit_current_file, fi); g_free(path_str); /* recursively set display names for path parents */ _check_native_display_names(fm_path_get_parent(path)); } else { GFile* gf; gf = fm_path_to_gfile(path); if(!_fm_file_info_job_get_info_for_gfile(fmjob, fi, gf, &err)) { if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED) { GFileInfo *inf; /* location by link isn't mounted; unfortunately we cannot launch a target if we don't know what kind of target we have; lets make a simplest directory-kind GFIleInfo */ /* FIXME: this may be dirty a bit */ g_error_free(err); err = NULL; inf = g_file_info_new(); g_file_info_set_file_type(inf, G_FILE_TYPE_DIRECTORY); g_file_info_set_name(inf, fm_path_get_basename(path)); g_file_info_set_display_name(inf, fm_path_get_basename(path)); fm_file_info_set_from_g_file_data(fi, gf, inf); g_object_unref(inf); } else { FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MILD); g_error_free(err); err = NULL; if(act == FM_JOB_RETRY) { g_object_unref(gf); continue; /* retry */ } fm_file_info_list_delete_link(job->file_infos, l); /* also calls unref */ goto _next; } } else if(G_UNLIKELY(job->flags & FM_FILE_INFO_JOB_EMIT_FOR_EACH_FILE)) fm_job_call_main_thread(fmjob, _emit_current_file, fi); /* recursively set display names for path parents */ _check_gfile_display_names(fm_path_get_parent(path), gf); _next: g_object_unref(gf); } l = next; } return TRUE; }
static gint on_ask_rename(FmFileOpsJob* job, FmFileInfo* src, FmFileInfo* dest, char** new_name, FmProgressDisplay* data) { int res; GtkBuilder* builder; GtkDialog *dlg; GtkImage *src_icon, *dest_icon; GtkLabel *src_fi, *dest_fi; GtkEntry *filename; GtkToggleButton *apply_all; char* tmp; const char* disp_size; FmPath* path; FmIcon* icon; /* return default operation if the user has set it */ if(data->default_opt) return data->default_opt; builder = gtk_builder_new(); path = fm_file_info_get_path(dest); icon = fm_file_info_get_icon(src); if(data->timer) g_timer_stop(data->timer); gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE); ensure_dlg(data); gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/ask-rename.ui", NULL); dlg = GTK_DIALOG(gtk_builder_get_object(builder, "dlg")); src_icon = GTK_IMAGE(gtk_builder_get_object(builder, "src_icon")); src_fi = GTK_LABEL(gtk_builder_get_object(builder, "src_fi")); dest_icon = GTK_IMAGE(gtk_builder_get_object(builder, "dest_icon")); dest_fi = GTK_LABEL(gtk_builder_get_object(builder, "dest_fi")); filename = GTK_ENTRY(gtk_builder_get_object(builder, "filename")); apply_all = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "apply_all")); gtk_window_set_transient_for(GTK_WINDOW(dlg), GTK_WINDOW(data->dlg)); gtk_image_set_from_gicon(src_icon, icon->gicon, GTK_ICON_SIZE_DIALOG); disp_size = fm_file_info_get_disp_size(src); if(disp_size) { tmp = g_strdup_printf(_("Type: %s\nSize: %s\nModified: %s"), fm_file_info_get_desc(src), disp_size, fm_file_info_get_disp_mtime(src)); } else { tmp = g_strdup_printf(_("Type: %s\nModified: %s"), fm_file_info_get_desc(src), fm_file_info_get_disp_mtime(src)); } gtk_label_set_text(src_fi, tmp); g_free(tmp); gtk_image_set_from_gicon(dest_icon, icon->gicon, GTK_ICON_SIZE_DIALOG); disp_size = fm_file_info_get_disp_size(dest); if(disp_size) { tmp = g_strdup_printf(_("Type: %s\nSize: %s\nModified: %s"), fm_file_info_get_desc(dest), fm_file_info_get_disp_size(dest), fm_file_info_get_disp_mtime(dest)); } else { tmp = g_strdup_printf(_("Type: %s\nModified: %s"), fm_file_info_get_desc(dest), fm_file_info_get_disp_mtime(dest)); } gtk_label_set_text(dest_fi, tmp); g_free(tmp); tmp = g_filename_display_name(fm_path_get_basename(path)); gtk_entry_set_text(filename, tmp); g_free(tmp); tmp = (char*)fm_file_info_get_disp_name(dest); /* FIXME: cast const to char */ g_object_set_data(G_OBJECT(filename), "old_name", tmp); g_signal_connect(filename, "changed", G_CALLBACK(on_filename_changed), gtk_builder_get_object(builder, "rename")); g_object_unref(builder); res = gtk_dialog_run(dlg); switch(res) { case RESPONSE_RENAME: *new_name = g_strdup(gtk_entry_get_text(filename)); res = FM_FILE_OP_RENAME; break; case RESPONSE_OVERWRITE: res = FM_FILE_OP_OVERWRITE; break; case RESPONSE_SKIP: res = FM_FILE_OP_SKIP; break; default: res = FM_FILE_OP_CANCEL; } if(gtk_toggle_button_get_active(apply_all)) { if(res == RESPONSE_OVERWRITE || res == FM_FILE_OP_SKIP) data->default_opt = res; } gtk_widget_destroy(GTK_WIDGET(dlg)); if(data->timer) g_timer_continue(data->timer); return res; }
gboolean _fm_file_ops_job_move_run(FmFileOpsJob* job) { GFile *dest_dir; GFileInfo* inf; GList* l; GError* err = NULL; FmJob* fmjob = FM_JOB(job); dev_t dest_dev = 0; gboolean ret = TRUE; FmDeepCountJob* dc; FmPath *parent = NULL; FmFolder *df, *sf = NULL; /* get information of destination folder */ g_return_val_if_fail(job->dest, FALSE); dest_dir = fm_path_to_gfile(job->dest); _retry_query_dest_info: inf = g_file_query_info(dest_dir, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL"," G_FILE_ATTRIBUTE_UNIX_DEVICE"," G_FILE_ATTRIBUTE_ID_FILESYSTEM"," G_FILE_ATTRIBUTE_UNIX_DEVICE, 0, fm_job_get_cancellable(fmjob), &err); if(inf) { job->dest_fs_id = g_intern_string(g_file_info_get_attribute_string(inf, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); dest_dev = g_file_info_get_attribute_uint32(inf, G_FILE_ATTRIBUTE_UNIX_DEVICE); /* needed by deep count */ g_object_unref(inf); } else { FmJobErrorAction act = fm_job_emit_error(fmjob, err, FM_JOB_ERROR_MODERATE); g_error_free(err); err = NULL; if(act == FM_JOB_RETRY) goto _retry_query_dest_info; else { g_object_unref(dest_dir); return FALSE; } } /* prepare the job, count total work needed with FmDeepCountJob */ dc = fm_deep_count_job_new(job->srcs, FM_DC_JOB_PREPARE_MOVE); fm_deep_count_job_set_dest(dc, dest_dev, job->dest_fs_id); fm_job_run_sync(FM_JOB(dc)); job->total = dc->total_size; if( fm_job_is_cancelled(FM_JOB(dc)) ) { g_object_unref(dest_dir); g_object_unref(dc); return FALSE; } g_object_unref(dc); g_debug("total size to move: %llu, dest_fs: %s", (long long unsigned int)job->total, job->dest_fs_id); fm_file_ops_job_emit_prepared(job); /* suspend updates for destination */ df = fm_folder_find_by_path(job->dest); if (df) fm_folder_block_updates(df); for(l = fm_path_list_peek_head_link(job->srcs); !fm_job_is_cancelled(fmjob) && l; l=l->next) { FmPath* path = FM_PATH(l->data); GFile* src = fm_path_to_gfile(path); GFile* dest; char* tmp_basename; /* do with updates for source */ if (fm_path_get_parent(path) != parent && fm_path_get_parent(path) != NULL) { FmFolder *pf; pf = fm_folder_find_by_path(fm_path_get_parent(path)); if (pf != sf) { if (sf) { fm_folder_unblock_updates(sf); g_object_unref(sf); } if (pf) fm_folder_block_updates(pf); sf = pf; } else if (pf) g_object_unref(pf); } parent = fm_path_get_parent(path); if(g_file_is_native(src) && g_file_is_native(dest_dir)) /* both are native */ tmp_basename = NULL; else if(g_file_is_native(src)) /* move from native to virtual */ tmp_basename = g_filename_to_utf8(fm_path_get_basename(path), -1, NULL, NULL, NULL); /* gvfs escapes it itself */ else /* move from virtual to native/virtual */ tmp_basename = fm_uri_subpath_to_native_subpath(fm_path_get_basename(path), NULL); dest = g_file_get_child(dest_dir, tmp_basename ? tmp_basename : fm_path_get_basename(path)); g_free(tmp_basename); if(!_fm_file_ops_job_move_file(job, src, NULL, dest, path, sf, df)) ret = FALSE; g_object_unref(src); g_object_unref(dest); if(!ret) break; } /* restore updates for destination and source */ if (df) { fm_folder_unblock_updates(df); g_object_unref(df); } if (sf) { fm_folder_unblock_updates(sf); g_object_unref(sf); } g_object_unref(dest_dir); return ret; }
gboolean _fm_file_ops_job_copy_run(FmFileOpsJob* job) { gboolean ret = TRUE; GFile *dest_dir; GList* l; FmJob* fmjob = FM_JOB(job); /* prepare the job, count total work needed with FmDeepCountJob */ FmDeepCountJob* dc = fm_deep_count_job_new(job->srcs, FM_DC_JOB_DEFAULT); FmFolder *df; /* let the deep count job share the same cancellable object. */ fm_job_set_cancellable(FM_JOB(dc), fm_job_get_cancellable(fmjob)); fm_job_run_sync(FM_JOB(dc)); job->total = dc->total_size; if(fm_job_is_cancelled(fmjob)) { g_object_unref(dc); return FALSE; } g_object_unref(dc); g_debug("total size to copy: %llu", (long long unsigned int)job->total); dest_dir = fm_path_to_gfile(job->dest); /* suspend updates for destination */ df = fm_folder_find_by_path(job->dest); if (df) fm_folder_block_updates(df); fm_file_ops_job_emit_prepared(job); for(l = fm_path_list_peek_head_link(job->srcs); !fm_job_is_cancelled(fmjob) && l; l=l->next) { FmPath* path = FM_PATH(l->data); GFile* src = fm_path_to_gfile(path); GFile* dest; char* tmp_basename; if(g_file_is_native(src) && g_file_is_native(dest_dir)) /* both are native */ tmp_basename = NULL; else if(g_file_is_native(src)) /* copy from native to virtual */ tmp_basename = g_filename_to_utf8(fm_path_get_basename(path), -1, NULL, NULL, NULL); /* gvfs escapes it itself */ else /* copy from virtual to native/virtual */ { /* if we drop URI query onto native filesystem, omit query part */ const char *basename = fm_path_get_basename(path); char *sub_name; sub_name = strchr(basename, '?'); if (sub_name) { sub_name = g_strndup(basename, sub_name - basename); basename = strrchr(sub_name, G_DIR_SEPARATOR); if (basename) basename++; else basename = sub_name; } tmp_basename = fm_uri_subpath_to_native_subpath(basename, NULL); g_free(sub_name); } dest = g_file_get_child(dest_dir, tmp_basename ? tmp_basename : fm_path_get_basename(path)); g_free(tmp_basename); if(!_fm_file_ops_job_copy_file(job, src, NULL, dest, NULL, df)) ret = FALSE; g_object_unref(src); g_object_unref(dest); } /* g_debug("finished: %llu, total: %llu", job->finished, job->total); */ fm_file_ops_job_emit_percent(job); /* restore updates for destination */ if (df) { fm_folder_unblock_updates(df); g_object_unref(df); } g_object_unref(dest_dir); return ret; }
static void test_path_child() { FmPath* parent = fm_path_get_home(); FmPath* path; g_print("\n"); path = fm_path_new_child(parent, "child"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "child"); fm_path_unref(path); path = fm_path_new_child(parent, "child/"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "child"); fm_path_unref(path); path = fm_path_new_child(parent, "child///"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "child"); fm_path_unref(path); path = fm_path_new_child(parent, ".."); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert(path == fm_path_get_parent(parent)); fm_path_unref(path); path = fm_path_new_child(parent, "../"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert(path == fm_path_get_parent(parent)); fm_path_unref(path); path = fm_path_new_child(parent, "/"); g_assert(path == parent); fm_path_unref(path); parent = fm_path_get_root(); path = fm_path_new_child(parent, ".."); g_assert(path == parent); fm_path_unref(path); path = fm_path_new_child(parent, "../"); g_assert(path == parent); fm_path_unref(path); parent = NULL; path = fm_path_new_child(parent, "/"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "/"); fm_path_unref(path); path = fm_path_new_child(parent, "//"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "/"); fm_path_unref(path); path = fm_path_new_child(parent, "///"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "/"); fm_path_unref(path); /* FIXME: how to handle this case? path = fm_path_new_child(parent, "/test"); g_printf("path->name = %s\n", path->name); g_assert_cmpstr(path->name, ==, "/test/"); fm_path_unref(path); */ path = fm_path_new_child(parent, "trash:"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///"); fm_path_unref(path); path = fm_path_new_child(parent, "trash:/"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///"); fm_path_unref(path); path = fm_path_new_child(parent, "trash:////"); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "trash:///"); fm_path_unref(path); path = fm_path_new_child(parent, ".."); g_printf("path->name = %s\n", fm_path_get_basename(path)); g_assert_cmpstr(fm_path_get_basename(path), ==, "/"); fm_path_unref(path); path = fm_path_new_child(parent, "../"); g_assert_cmpstr(fm_path_get_basename(path), ==, "/"); fm_path_unref(path); /* path = fm_path_new_child(parent, ".."); g_assert(path == NULL); path = fm_path_new_child(parent, "."); g_assert(path == NULL); */ }