static void on_file_info_job_finished(FmFileInfoJob* job, gpointer user_data) { FmPlacesModel* model = FM_PLACES_MODEL(user_data); GList* l; GtkTreeIter it; FmPlaceItem* item; FmFileInfo* fi; /* g_debug("file info job finished"); */ model->jobs = g_slist_remove(model->jobs, job); if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &it)) return; if(fm_list_is_empty(job->file_infos)) return; /* optimize for one file case */ if(fm_list_get_length(job->file_infos) == 1) { fi = FM_FILE_INFO(fm_list_peek_head(job->file_infos)); do { item = NULL; gtk_tree_model_get(GTK_TREE_MODEL(model), &it, FM_PLACES_MODEL_COL_INFO, &item, -1); if( item && item->fi && item->fi->path && fm_path_equal(item->fi->path, fi->path) ) { fm_file_info_unref(item->fi); item->fi = fm_file_info_ref(fi); break; } }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &it)); } else { do { item = NULL; gtk_tree_model_get(GTK_TREE_MODEL(model), &it, FM_PLACES_MODEL_COL_INFO, &item, -1); if( item && item->fi && item->fi->path ) { for(l = fm_list_peek_head_link(job->file_infos); l; l = l->next ) { fi = FM_FILE_INFO(l->data); if(fm_path_equal(item->fi->path, fi->path)) { fm_file_info_unref(item->fi); item->fi = fm_file_info_ref(fi); /* remove the file from list to speed up further loading. * This won't cause problem since nobody else if using the list. */ fm_list_delete_link(job->file_infos, l); break; } } } }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &it)); } }
ExecFileDialog::ExecFileDialog(FmFileInfo* file, QWidget* parent, Qt::WindowFlags f): QDialog (parent, f), fileInfo_(fm_file_info_ref(file)), result_(FM_FILE_LAUNCHER_EXEC_CANCEL), ui(new Ui::ExecFileDialog()) { ui->setupUi(this); // show file icon FmIcon* icon = fm_file_info_get_icon(fileInfo_); ui->icon->setPixmap(IconTheme::icon(icon).pixmap(QSize(48, 48))); QString msg; if(fm_file_info_is_text(file)) { msg = tr("This text file '%1' seems to be an executable script.\nWhat do you want to do with it?") .arg(QString::fromUtf8(fm_file_info_get_disp_name(file))); ui->execTerm->setDefault(true); } else { msg= tr("This file '%1' is executable. Do you want to execute it?") .arg(QString::fromUtf8(fm_file_info_get_disp_name(file))); ui->exec->setDefault(true); ui->open->hide(); } ui->msg->setText(msg); }
static FmFileInfo *_fetch_file_info_for_shortcut(const char *target, GAppLaunchContext* ctx, FmFileLauncher* launcher, gpointer user_data) { FmFileInfoJob *job; QueryErrorData data; FmFileInfo *fi; FmPath *path; job = fm_file_info_job_new(NULL, 0); /* bug #3614794: the shortcut target is a commandline argument */ path = fm_path_new_for_commandline_arg(target); fm_file_info_job_add(job, path); fm_path_unref(path); data.ctx = ctx; data.launcher = launcher; data.user_data = user_data; g_signal_connect(job, "error", G_CALLBACK(on_query_target_info_error), &data); fi = NULL; if (fm_job_run_sync_with_mainloop(FM_JOB(job))) fi = fm_file_info_ref(fm_file_info_list_peek_head(job->file_infos)); g_signal_handlers_disconnect_by_func(job, on_query_target_info_error, &data); g_object_unref(job); return fi; }
void fm_dnd_dest_set_dest_file(FmDndDest* dd, FmFileInfo* dest_file) { if(dd->dest_file == dest_file) return; if(dd->dest_file) fm_file_info_unref(dd->dest_file); dd->dest_file = dest_file ? fm_file_info_ref(dest_file) : NULL; }
// public APIs QModelIndex DirTreeModel::addRoot(FmFileInfo* root) { DirTreeModelItem* item = new DirTreeModelItem(root, this); int row = rootItems_.count(); beginInsertRows(QModelIndex(), row, row); item->fileInfo_ = fm_file_info_ref(root); rootItems_.append(item); // add_place_holder_child_item(model, item_l, NULL, FALSE); endInsertRows(); return QModelIndex(); }
static gpointer queue_add_file(FmJob* fmjob, gpointer user_data) { FmDirListJob* job = FM_DIR_LIST_JOB(fmjob); FmFileInfo* file = FM_FILE_INFO(user_data); /* this callback is called from the main thread */ /* g_print("queue_add_file: %s\n", fm_file_info_get_disp_name(file)); */ job->files_to_add = g_slist_prepend(job->files_to_add, fm_file_info_ref(file)); if(job->delay_add_files_handler == 0) job->delay_add_files_handler = g_timeout_add_seconds_full(G_PRIORITY_LOW, 1, emit_found_files, g_object_ref(job), g_object_unref); return NULL; }
void on_file_info_finished(FmFileInfoJob* job, FmFolder* folder) { GList* l; GSList* files_to_add = NULL; GSList* files_to_update = NULL; for(l=fm_list_peek_head_link(job->file_infos);l;l=l->next) { FmFileInfo* fi = (FmFileInfo*)l->data; GList* l2 = _fm_folder_get_file_by_name(folder, fi->path->name); if(l2) /* the file is already in the folder, update */ { FmFileInfo* fi2 = (FmFileInfo*)l2->data; /* FIXME: will fm_file_info_copy here cause problems? * the file info might be referenced by others, too. * we're mofifying an object referenced by others. * we should redesign the API, or document this clearly * in future API doc. */ fm_file_info_copy(fi2, fi); files_to_update = g_slist_prepend(files_to_update, fi2); } else { files_to_add = g_slist_prepend(files_to_add, fi); fm_file_info_ref(fi); fm_list_push_tail(folder->files, fi); } } if(files_to_add) { g_signal_emit(folder, signals[FILES_ADDED], 0, files_to_add); g_slist_free(files_to_add); } if(files_to_update) { g_signal_emit(folder, signals[FILES_CHANGED], 0, files_to_update); g_slist_free(files_to_update); } folder->pending_jobs = g_slist_remove(folder->pending_jobs, job); }
FmFileInfoList* fm_folder_view_get_selected_files(FmFolderView* fv) { FmFileInfoList* fis; GList *sels = fm_folder_view_get_selected_tree_paths(fv); GList *l, *next; if(!sels) return NULL; fis = fm_file_info_list_new(); for(l = sels;l;l=next) { FmFileInfo* fi; GtkTreeIter it; GtkTreePath* tp = (GtkTreePath*)l->data; gtk_tree_model_get_iter(fv->model, &it, l->data); gtk_tree_model_get(fv->model, &it, COL_FILE_INFO, &fi, -1); gtk_tree_path_free(tp); next = l->next; l->data = fm_file_info_ref( fi ); l->prev = l->next = NULL; fm_list_push_tail_link(fis, l); } return fis; }
static void on_job_finished(FmDirListJob* job, FmFolder* folder) { GList* l; GSList* files = NULL; /* actually manually disconnecting from 'finished' signal is not * needed since the signal is only emit once, and later the job * object will be distroyed very soon. */ /* g_signal_handlers_disconnect_by_func(job, on_job_finished, folder); */ for(l = fm_list_peek_head_link(job->files); l; l=l->next) { FmFileInfo* inf = (FmFileInfo*)l->data; files = g_slist_prepend(files, inf); fm_list_push_tail(folder->files, inf); } if(G_LIKELY(files)) g_signal_emit(folder, signals[FILES_ADDED], 0, files); if(job->dir_fi) folder->dir_fi = fm_file_info_ref(job->dir_fi); folder->job = NULL; /* the job object will be freed in idle handler. */ g_signal_emit(folder, signals[LOADED], 0); }
/** * fm_dir_list_job_set_dir_info * @job: the job that collected listing * @info: a FmFileInfo of the directory being loaded. * * This API is called by the implementation of FmDirListJob only. * Application developers should not use this API most of the time. * * Since: 1.0.2 */ void fm_dir_list_job_set_dir_info(FmDirListJob* job, FmFileInfo* info) { if(job->dir_fi) fm_file_info_unref(job->dir_fi); job->dir_fi = fm_file_info_ref(info); }
static inline FmFolderItem* fm_folder_item_new(FmFileInfo* inf) { FmFolderItem* item = g_slice_new0(FmFolderItem); item->inf = fm_file_info_ref(inf); return item; }
FmThumbnailRequest* fm_thumbnail_request(FmFileInfo* src_file, guint size, FmThumbnailReadyCallback callback, gpointer user_data) { FmThumbnailRequest* req; ThumbnailTask* task; GdkPixbuf* pix; req = g_slice_new(FmThumbnailRequest); req->fi = fm_file_info_ref(src_file); req->size = size; req->callback = callback; req->user_data = user_data; req->pix = NULL; DEBUG("request thumbnail: %s", src_file->path->name); G_LOCK(queue); /* FIXME: find in the cache first to see if thumbnail is already cached */ pix = find_thumbnail_in_hash(src_file->path, size); if(pix) { DEBUG("cache found!"); req->pix = (GdkPixbuf*)g_object_ref(pix); /* call the ready callback in main loader_thread_id from idle handler. */ g_queue_push_tail(&ready_queue, req); if( 0 == ready_idle_handler ) /* schedule an idle handler if there isn't one. */ ready_idle_handler = g_idle_add_full(G_PRIORITY_LOW, on_ready_idle, NULL, NULL); G_UNLOCK(queue); return req; } /* if it's not cached, add it to the loader_queue for loading. */ task = find_queued_task(&loader_queue, src_file); if(!task) { task = g_slice_new0(ThumbnailTask); task->fi = fm_file_info_ref(src_file); g_queue_push_tail(&loader_queue, task); } else { DEBUG("task already in the queue: %p", task); } if(size > 128) task->flags |= LOAD_LARGE; else task->flags |= LOAD_NORMAL; task->requests = g_list_append(task->requests, req); if(!loader_thread_id) loader_thread_id = g_thread_create( load_thumbnail_thread, NULL, FALSE, NULL); G_UNLOCK(queue); return req; }
void load_thumbnails(ThumbnailTask* task) { GList* l; GdkPixbuf* normal_pix = NULL; GdkPixbuf* large_pix = NULL; const char* normal_path = task->normal_path; const char* large_path = task->large_path; if( IS_CANCELLED(task) ) goto _out; DEBUG("loading: %s, %s", task->fi->path->name, normal_path); if(task->flags & LOAD_NORMAL) { normal_pix = gdk_pixbuf_new_from_file(normal_path, NULL); if(!normal_pix || is_thumbnail_outdated(normal_pix, normal_path, task->fi->mtime)) { /* normal_pix is freed in is_thumbnail_outdated() if it's out of date. */ /* generate normal size thumbnail */ task->flags |= GENERATE_NORMAL; normal_pix = NULL; /* DEBUG("need to generate normal thumbnail"); */ } else DEBUG("normal thumbnail loaded: %p", normal_pix); } if( IS_CANCELLED(task) ) goto _out; if(task->flags & LOAD_LARGE) { large_pix = gdk_pixbuf_new_from_file(large_path, NULL); if(!large_pix || is_thumbnail_outdated(large_pix, large_path, task->fi->mtime)) { /* large_pix is freed in is_thumbnail_outdated() if it's out of date. */ /* generate large size thumbnail */ task->flags |= GENERATE_LARGE; large_pix = NULL; } } if( IS_CANCELLED(task) ) goto _out; if(task->flags & (GENERATE_NORMAL|GENERATE_LARGE)) /* need to re-generate some thumbnails */ { GList* generate_reqs = NULL, *l; ThumbnailTask* generate_task; #if 0 /* all requested thumbnails need to be re-generated. */ if( ((task->flags & LOAD_NORMAL|LOAD_LARGE) << 2) == (task->flags & (GENERATE_NORMAL|GENERATE_LARGE)) ) { task->uri = g_strdup(task->uri); task->normal_path = g_strdup(normal_path); task->large_path = g_strdup(large_path); task->flags |= ALLOC_STRINGS; /* push the whole task into generator queue */ queue_generate(task); return; } #endif /* remove all requests which requires re-generating thumbnails from task and gather them in a list */ for(l=task->requests; l; ) { FmThumbnailRequest* req = (FmThumbnailRequest*)l->data; GList* next = l->next; if(req->size <= 128) /* need normal thumbnail */ { if(task->flags & GENERATE_NORMAL) { task->requests = g_list_remove_link(task->requests, l); generate_reqs = g_list_concat(generate_reqs, l); } } else /* need large thumbnail */ { if(task->flags & GENERATE_LARGE) { task->requests = g_list_remove_link(task->requests, l); generate_reqs = g_list_concat(generate_reqs, l); } } l = next; } /* this list contains requests requiring regeration of thumbnails */ if(generate_reqs) { generate_task = g_slice_new0(ThumbnailTask); generate_task->flags = task->flags | ALLOC_STRINGS; generate_task->fi = fm_file_info_ref(task->fi); generate_task->requests = generate_reqs; generate_task->uri = g_strdup(task->uri); generate_task->normal_path = g_strdup(task->normal_path); generate_task->large_path = g_strdup(task->large_path); DEBUG("queue regenerate for :%s", task->fi->path->name); /* queue the re-generation task */ queue_generate(generate_task); } } _out: G_LOCK(queue); /* thumbnails which don't require re-generation should all be loaded at this point. */ if( IS_CANCELLED(task) || !task->requests ) thumbnail_task_free(task); else thumbnail_task_finish(task, normal_pix, large_pix); cur_loading = NULL; /* task is freed in thumbnail_task_finish() */ G_UNLOCK(queue); if(normal_pix) g_object_unref(normal_pix); if(large_pix) g_object_unref(large_pix); return; }