/** * fm_job_askv * @job: the job that calls main thread * @question: the text to ask the user * @options: list of choices to give the user * * Asks the user for some interactions. The user will have a list of * available options and should make a choice. * * This APIs is private to #FmJob and should only be used in the * implementation of classes derived from #FmJob. * * This function should be called from working thread only. * * Returns: user's choice. * * Since: 0.1.0 */ gint fm_job_askv(FmJob* job, const char* question, gchar* const *options) { struct AskData data; data.question = question; data.options = options; return GPOINTER_TO_INT(fm_job_call_main_thread(job, ask_in_main_thread, &data)); }
/** * fm_job_emit_error * @job: a job that emitted the signal * @err: an error descriptor * @severity: severity of the error * * Emits an #FmJob::error signal in the main thread to notify it when an * error occurs. * The return value of this function is the return value returned by * the connected signal handlers. * If @severity is FM_JOB_ERROR_CRITICAL, the returned value is ignored and * fm_job_cancel() is called to abort the job. Otherwise, the signal * handler of this error can return FM_JOB_RETRY to ask for retrying the * failed operation, return FM_JOB_CONTINUE to ignore the error and * continue the remaining job, or return FM_JOB_ABORT to abort the job. * If FM_JOB_ABORT is returned by the signal handler, fm_job_cancel() * will be called in fm_job_emit_error(). * * This APIs is private to #FmJob and should only be used in the * implementation of classes derived from #FmJob. * * This function should be called from working thread only. * * Returns: action that should be performed on that error. * * Since: 0.1.0 */ FmJobErrorAction fm_job_emit_error(FmJob* job, GError* err, FmJobErrorSeverity severity) { FmJobErrorAction ret; struct ErrData data; g_return_val_if_fail(err, FM_JOB_ABORT); data.err = err; data.severity = severity; ret = GPOINTER_TO_UINT(fm_job_call_main_thread(job, error_in_main_thread, &data)); if(severity == FM_JOB_ERROR_CRITICAL || ret == FM_JOB_ABORT) { ret = FM_JOB_ABORT; fm_job_cancel(job); } /* If the job is already cancelled, retry is not allowed. */ if(ret == FM_JOB_RETRY ) { if(job->cancel || (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_CANCELLED)) ret = FM_JOB_CONTINUE; } return ret; }
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; }
/** * fm_dir_list_job_add_found_file * @job: the job that collected listing * @file: a FmFileInfo of the newly found file * * This API may be called by the classes derived of FmDirListJob only. * Application developers should not use this API. * When a new file is found in the dir being listed, implementations * of FmDirListJob should call this API with the info of the newly found * file. The FmFileInfo will be added to the found file list. * * If emission of the #FmDirListJob::files-found signal is turned on by * fm_dir_list_job_set_incremental(), the signal will be emitted * for the newly found files after several new files are added. * See the document for the signal for more detail. * * Since: 1.0.2 */ void fm_dir_list_job_add_found_file(FmDirListJob* job, FmFileInfo* file) { fm_file_info_list_push_tail(job->files, file); if(G_UNLIKELY(job->emit_files_found)) fm_job_call_main_thread(FM_JOB(job), queue_add_file, file); }