FilePropsDialog::FilePropsDialog(FmFileInfoList* files, QWidget* parent, Qt::WindowFlags f): QDialog(parent, f), fileInfos_(fm_file_info_list_ref(files)), singleType(fm_file_info_list_is_same_type(files)), singleFile(fm_file_info_list_get_length(files) == 1 ? true:false), fileInfo(fm_file_info_list_peek_head(files)), mimeType(NULL) { setAttribute(Qt::WA_DeleteOnClose); ui = new Ui::FilePropsDialog(); ui->setupUi(this); if(singleType) { mimeType = fm_mime_type_ref(fm_file_info_get_mime_type(fileInfo)); } FmPathList* paths = fm_path_list_new_from_file_info_list(files); deepCountJob = fm_deep_count_job_new(paths, FM_DC_JOB_DEFAULT); fm_path_list_unref(paths); initGeneralPage(); initPermissionsPage(); }
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; }
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; }
GtkWidget *fm_file_properties_widget_new (FmFileInfoList *files, gboolean toplevel) { GtkBuilder *builder=gtk_builder_new (); GtkWidget *dlg, *total_size; FmFilePropData *data; FmPathList *paths; gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); data = g_slice_new0 (FmFilePropData); data->files = fm_list_ref (files); data->single_type = fm_file_info_list_is_same_type (files); data->single_file = (fm_list_get_length (files) == 1); data->file_info = fm_list_peek_head (files); FmMimeType *fi_mime_type = fm_file_info_get_mime_type (data->file_info, FALSE); if (data->single_type) data->mime_type = fi_mime_type; // FIXME_pcm: do we need ref counting here? paths = fm_path_list_new_from_file_info_list (files); data->dc_job = fm_deep_count_job_new (paths, FM_DC_JOB_DEFAULT); fm_list_unref (paths); if (toplevel) { gtk_builder_add_from_string (builder, PROPERTIES_DLG, -1, NULL); GET_WIDGET (dlg); gtk_dialog_set_alternative_button_order (GTK_DIALOG (data->dlg), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); } else { #if 0 // FIXME_pcm: is this really useful? const char *names[]= {"notebook", NULL}; gtk_builder_add_objects_from_file (builder, UI_FILE, names, NULL); data->dlg = (GtkWidget*)gtk_builder_get_object (builder, "notebook"); #endif } dlg = data->dlg; GET_WIDGET (icon); GET_WIDGET (name); GET_WIDGET (dir); GET_WIDGET (target); GET_WIDGET (target_label); GET_WIDGET (type); GET_WIDGET (open_with_label); GET_WIDGET (open_with); GET_WIDGET (total_size); GET_WIDGET (size_on_disk); GET_WIDGET (mtime); GET_WIDGET (atime); GET_WIDGET (owner); GET_WIDGET (group); GET_WIDGET (owner_perm); GET_WIDGET (group_perm); GET_WIDGET (other_perm); GET_WIDGET (exec); g_object_unref (builder); init_application_list (data); data->timeout = g_timeout_add (600, (GSourceFunc)on_timeout, data); g_signal_connect (dlg, "response", G_CALLBACK (on_response), data); g_signal_connect_swapped (dlg, "destroy", G_CALLBACK (fm_file_prop_data_free), data); g_signal_connect (data->dc_job, "finished", G_CALLBACK (on_finished), data); fm_job_run_async (data->dc_job); update_ui (data); return dlg; }