/***************************************************************************************** * ... * * ****************************************************************************************/ void fm_dir_tree_model_expand_row (FmDirTreeModel *dir_tree_model, GtkTreeIter *it, GtkTreePath *tree_path) { //TREEVIEW_DEBUG ("TREEVIEW_DEBUG: fm_dir_tree_model_expand_row\n"); GList *item_list = (GList*) it->user_data; FmDirTreeItem *dir_tree_item = (FmDirTreeItem*) item_list->data; g_return_if_fail (dir_tree_item != NULL); if (dir_tree_item->n_expand == 0) { // Dynamically load content of the folder... FmFolder *folder = fm_dir_tree_item_set_folder (item_list); // If the folder is already loaded, call "loaded" handler ourselves... if (fm_folder_get_is_loaded (folder)) { FmDirTreeItem *dir_tree_item = (FmDirTreeItem*) item_list->data; GSList *files = fm_list_peek_head_link (folder->files); fm_dir_tree_item_load_folder (folder, files, item_list, FALSE); fm_dir_tree_item_on_folder_loaded (dir_tree_item); } else { //TREEVIEW_DEBUG ("NOT loaded !!!\n"); } } dir_tree_item->n_expand++; }
void fm_folder_view_select_file_paths(FmFolderView* fv, FmPathList* paths) { GList* l; for(l = fm_list_peek_head_link(paths);l; l=l->next) { FmPath* path = FM_PATH(l->data); fm_folder_view_select_file_path(fv, path); } }
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)); } }
FmPathList* fm_path_list_new_from_file_info_list(FmFileInfoList* fis) { FmPathList* list = fm_path_list_new(); GList* l; for(l=fm_list_peek_head_link(fis);l;l=l->next) { FmFileInfo* fi = (FmFileInfo*)l->data; fm_list_push_tail(list, fi->path); } return list; }
GList* _fm_folder_get_file_by_name(FmFolder* folder, const char* name) { GList* l = fm_list_peek_head_link(folder->files); for(;l;l=l->next) { FmFileInfo* fi = (FmFileInfo*)l->data; if(strcmp(fi->path->name, name) == 0) return l; } return NULL; }
void fm_folder_model_set_folder(FmFolderModel* model, FmFolder* dir) { GSequenceIter *it; if( model->dir == dir ) return; model->iter_age++; if( model->dir ) { g_signal_handlers_disconnect_by_func(model->dir, _fm_folder_model_files_added, model); g_signal_handlers_disconnect_by_func(model->dir, _fm_folder_model_files_removed, model); g_signal_handlers_disconnect_by_func(model->dir, _fm_folder_model_files_changed, model); g_signal_handlers_disconnect_by_func(model->dir, on_folder_loaded, model); g_sequence_free(model->items); g_sequence_free(model->hidden); g_object_unref(model->dir); } model->dir = dir; model->items = g_sequence_new((GDestroyNotify)fm_folder_item_free); model->hidden = g_sequence_new((GDestroyNotify)fm_folder_item_free); if( !dir ) return; model->dir = (FmFolder*)g_object_ref(model->dir); g_signal_connect(model->dir, "files-added", G_CALLBACK(_fm_folder_model_files_added), model); g_signal_connect(model->dir, "files-removed", G_CALLBACK(_fm_folder_model_files_removed), model); g_signal_connect(model->dir, "files-changed", G_CALLBACK(_fm_folder_model_files_changed), model); g_signal_connect(model->dir, "loaded", G_CALLBACK(on_folder_loaded), model); if( !fm_list_is_empty(dir->files) ) { GList *l; for( l = fm_list_peek_head_link(dir->files); l; l = l->next ) _fm_folder_model_add_file(model, (FmFileInfo*)l->data); } if( fm_folder_get_is_loaded(model->dir) ) /* if it's already loaded */ on_folder_loaded(model->dir, model); /* emit 'loaded' signal */ }
void fm_path_list_write_uri_list(FmPathList* pl, GString* buf) { GList* l; for(l = fm_list_peek_head_link(pl); l; l=l->next) { FmPath* path = (FmPath*)l->data; char* uri = fm_path_to_uri(path); g_string_append(buf, uri); g_free(uri); if(l->next) g_string_append(buf, "\r\n"); } }
void on_open_in_new_win(GtkAction* act, FmMainWin* win) { FmPathList* sels = fm_folder_view_get_selected_file_paths(FM_FOLDER_VIEW(win->folder_view)); GList* l; for( l = fm_list_peek_head_link(sels); l; l=l->next ) { FmPath* path = (FmPath*)l->data; win = fm_main_win_new(); gtk_window_set_default_size(GTK_WINDOW(win), 640, 480); fm_main_win_chdir(win, path); gtk_window_present(GTK_WINDOW(win)); } fm_list_unref(sels); }
static void on_drag_data_get ( GtkWidget *src_widget, GdkDragContext *drag_context, GtkSelectionData *sel_data, guint info, guint time, FmDndSrc* ds ) { GdkAtom type; /* Don't call the default handler */ g_signal_stop_emission_by_name( src_widget, "drag-data-get" ); drag_context->actions = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK; type = gdk_atom_intern_static_string(fm_default_dnd_src_targets[info].target); switch( info ) { case FM_DND_SRC_TARGET_FM_LIST: /* just store the pointer in GtkSelection since this is used * within the same app. */ gtk_selection_data_set(sel_data, type, 8, &ds->files, sizeof(gpointer)); break; case FM_DND_SRC_TARGET_URI_LIST: { gchar* uri; GString* uri_list = g_string_sized_new( 8192 ); GList* l; FmFileInfo* file; char* full_path; for( l = fm_list_peek_head_link(ds->files); l; l=l->next ) { file = (FmFileInfo*)l->data; uri = fm_path_to_uri(file->path); g_string_append( uri_list, uri ); g_free( uri ); g_string_append( uri_list, "\r\n" ); } gtk_selection_data_set ( sel_data, type, 8, ( guchar* ) uri_list->str, uri_list->len + 1 ); g_string_free( uri_list, TRUE ); } break; } }
gboolean fm_launch_paths(GAppLaunchContext* ctx, GList* paths, FmFileLauncher* launcher, gpointer user_data) { FmJob* job = fm_file_info_job_new(NULL); 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; }
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); }
gboolean fm_deep_count_job_run(FmJob* job) { FmDeepCountJob* dc = (FmDeepCountJob*)job; GList* l; l = fm_list_peek_head_link(dc->paths); for(; !fm_job_is_cancelled(job) && l; l=l->next) { FmPath* path = FM_PATH(l->data); if(fm_path_is_native(path)) /* if it's a native file, use posix APIs */ deep_count_posix( dc, path ); else { GFile* gf = fm_path_to_gfile(path); deep_count_gio( dc, NULL, gf ); g_object_unref(gf); } } return TRUE; }
gboolean on_dnd_dest_files_dropped(FmDndDest* dd, GdkDragAction action, int info_type, FmFileInfoList* files, FmPlacesView* view) { FmPath* dest; GList* l; gboolean ret = FALSE; dest = fm_dnd_dest_get_dest_path(dd); /* g_debug("action= %d, %d files-dropped!, info_type: %d", action, fm_list_get_length(files), info_type); */ if(!dest && action == GDK_ACTION_LINK) /* add bookmarks */ { GtkTreePath* tp = view->dest_row; if(tp) { const GtkTreePath* sep = fm_places_model_get_separator_path(FM_PLACES_MODEL(model)); int idx = gtk_tree_path_get_indices(tp)[0] - gtk_tree_path_get_indices(sep)[0]; if(view->dest_pos == GTK_TREE_VIEW_DROP_BEFORE) --idx; for( l=fm_list_peek_head_link(files); l; l=l->next, ++idx ) { FmBookmarkItem* item; FmFileInfo* fi = FM_FILE_INFO(l->data); if(fm_file_info_is_dir(fi)) item = fm_bookmarks_insert( FM_PLACES_MODEL(model)->bookmarks, fi->path, fi->disp_name, idx); /* we don't need to add item to places view. Later the bookmarks will be reloaded. */ } } ret = TRUE; } if(view->dest_row) { gtk_tree_path_free(view->dest_row); view->dest_row = NULL; } return ret; }
void fm_folder_reload(FmFolder* folder) { /* FIXME: remove all items and re-run a dir list job. */ GSList* files_to_del = NULL; GList* l = fm_list_peek_head_link(folder->files); if(l) { for(;l;l=l->next) { FmFileInfo* fi = (FmFileInfo*)l->data; files_to_del = g_slist_prepend(files_to_del, fi); } g_signal_emit(folder, signals[FILES_REMOVED], 0, files_to_del); fm_list_clear(folder->files); /* fm_file_info_unref will be invoked. */ g_slist_free(files_to_del); } folder->job = fm_dir_list_job_new(folder->dir_path, FALSE); g_signal_connect(folder->job, "finished", G_CALLBACK(on_job_finished), folder); g_signal_connect(folder->job, "error", G_CALLBACK(on_job_err), folder); fm_job_run_async(FM_JOB(folder->job)); }
/********************************************************************* * ... * * ********************************************************************/ FmJob *fm_file_info_job_new (FmPathList *files_to_query, FmFileInfoJobFlags flags) { FmFileInfoJob *job = (FmFileInfoJob*) g_object_new (FM_TYPE_FILE_INFO_JOB, NULL); job->flags = flags; if (!files_to_query) return (FmJob*) job; FmFileInfoList *file_infos = job->file_infos; GList *l; for (l = fm_list_peek_head_link (files_to_query); l; l=l->next) { FmPath *path = (FmPath*) l->data; FmFileInfo *file_info = fm_file_info_new_for_path (path); fm_list_push_tail_noref (file_infos, file_info); } return (FmJob*) job; }
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); }
static void get_data(GtkClipboard *clip, GtkSelectionData *sel, guint info, gpointer user_data) { FmPathList* files = (FmPathList*)user_data; GString* uri_list; if(info == KDE_CUT_SEL) { /* set application/kde-cutselection data */ if(is_cut) gtk_selection_data_set(sel, sel->target, 8, "1", 2); return; } uri_list = g_string_sized_new(4096); if(info == GNOME_COPIED_FILES) g_string_append(uri_list, is_cut ? "cut\n" : "copy\n"); if(info == UTF8_STRING) { GList* l = fm_list_peek_head_link(files); while(l) { FmPath* path = (FmPath*)l->data; char* str = fm_path_to_str(path); g_string_append(uri_list, str); g_string_append_c(uri_list, '\n'); g_free(str); l=l->next; } } else/* text/uri-list format */ { fm_path_list_write_uri_list(files, uri_list); } gtk_selection_data_set(sel, sel->target, 8, uri_list->str, uri_list->len + 1); g_string_free(uri_list, TRUE); }
// FIXME_pcm: error handling static gboolean launch_program (FmArchiver *archiver, GAppLaunchContext *ctx, const char *cmd, FmPathList *files, FmPath *dir) { GDesktopAppInfo *app; char *_cmd = NULL; const char *dir_place_holder; GKeyFile *dummy; char *tmp; if (dir && (dir_place_holder = strstr (cmd, "%d"))) { char *dir_str; int len; if (strstr (cmd, "%U") || strstr (cmd, "%u")) // supports URI dir_str = fm_path_to_uri (dir); else { GFile *gf = fm_path_to_gfile (dir); // FIXME_pcm: convert dir to fuse-based local path if needed. dir_str = g_file_get_path (gf); g_object_unref (gf); } // replace all % with %% so encoded URI can be handled correctly when parsing Exec key. tmp = fm_str_replace (dir_str, "%", "%%"); g_free (dir_str); dir_str = tmp; // quote the path or URI tmp = g_shell_quote (dir_str); g_free (dir_str); dir_str = tmp; len = strlen (cmd) - 2 + strlen (dir_str) + 1; _cmd = g_malloc (len); len = (dir_place_holder - cmd); strncpy (_cmd, cmd, len); strcpy (_cmd + len, dir_str); strcat (_cmd, dir_place_holder + 2); g_free (dir_str); cmd = _cmd; } // create a fake key file to cheat GDesktopAppInfo dummy = g_key_file_new (); g_key_file_set_string (dummy, G_KEY_FILE_DESKTOP_GROUP, "Type", "Application"); g_key_file_set_string (dummy, G_KEY_FILE_DESKTOP_GROUP, "Name", archiver->program); // replace all % with %% so encoded URI can be handled correctly when parsing Exec key. g_key_file_set_string (dummy, G_KEY_FILE_DESKTOP_GROUP, "Exec", cmd); app = g_desktop_app_info_new_from_keyfile (dummy); g_key_file_free (dummy); g_debug ("cmd = %s", cmd); if (app) { GList *uris = NULL, *l; for (l = fm_list_peek_head_link (files); l; l=l->next) { FmPath *path = FM_PATH (l->data); uris = g_list_prepend (uris, fm_path_to_uri (path)); } fm_app_info_launch_uris ((GAppInfo *) app, uris, ctx, NULL); g_list_foreach (uris, (GFunc)g_free, NULL); g_list_free (uris); } g_free (_cmd); return TRUE; }
void on_dnd_dest_files_dropped(FmDndDest* dd, GdkDragAction action, int info_type, FmList* files, FmPlacesView* view) { FmPath* dest; GList* l; dest = fm_dnd_dest_get_dest_path(dd); g_debug("action= %d, %d files-dropped!, info_type: %d", action, fm_list_get_length(files), info_type); if(action != GDK_ACTION_LINK) { if(fm_list_is_file_info_list(files)) files = fm_path_list_new_from_file_info_list(files); else fm_list_ref(files); } switch(action) { case GDK_ACTION_MOVE: if(fm_path_is_trash_root(dest)) fm_trash_files(files); else fm_move_files(files, dest); break; case GDK_ACTION_COPY: fm_copy_files(files, dest); break; case GDK_ACTION_LINK: { GtkTreePath* tp = view->dest_row; if(tp) { GtkTreePath* sep = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &sep_it); int idx = gtk_tree_path_get_indices(tp)[0] - gtk_tree_path_get_indices(sep)[0]; gtk_tree_path_free(sep); if(view->dest_pos == GTK_TREE_VIEW_DROP_BEFORE) --idx; for( l=fm_list_peek_head_link(files); l; l=l->next, ++idx ) { FmBookmarkItem* item; if(fm_list_is_file_info_list(files)) { FmFileInfo* fi = (FmFileInfo*)l->data; item = fm_bookmarks_insert( bookmarks, fi->path, fi->disp_name, idx); } else { FmPath* path = (FmPath*)l->data; char* disp_name = g_filename_display_name(path->name); item = fm_bookmarks_insert( bookmarks, path, disp_name, idx); g_free(disp_name); } /* we don't need to add item to places view. Later the bookmarks will be reloaded. */ } } } break; } fm_list_unref(files); if(view->dest_row) { gtk_tree_path_free(view->dest_row); view->dest_row = NULL; } }
static gboolean on_show_dlg (FmProgressDisplay *data) { GtkBuilder *builder = gtk_builder_new (); GtkWidget *to, *to_label; FmPath *dest; const char *title = NULL; GtkTextTagTable *tag_table = gtk_text_tag_table_new (); gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); gtk_builder_add_from_string (builder, PROGRESS_DLG, -1, NULL); data->dlg = (GtkWidget*) gtk_builder_get_object (builder, "dlg"); g_signal_connect (data->dlg, "response", (GCallback) on_response, data); to_label = (GtkWidget*) gtk_builder_get_object (builder, "to_label"); to = (GtkWidget*) gtk_builder_get_object (builder, "dest"); data->icon = (GtkWidget*) gtk_builder_get_object (builder, "icon"); data->msg = (GtkWidget*) gtk_builder_get_object (builder, "msg"); data->act = (GtkWidget*) gtk_builder_get_object (builder, "action"); data->src = (GtkWidget*) gtk_builder_get_object (builder, "src"); data->dest = (GtkWidget*) gtk_builder_get_object (builder, "dest"); data->current = (GtkWidget*) gtk_builder_get_object (builder, "current"); data->progress = (GtkWidget*) gtk_builder_get_object (builder, "progress"); data->error_pane = (GtkWidget*) gtk_builder_get_object (builder, "error_pane"); data->error_msg = (GtkWidget*) gtk_builder_get_object (builder, "error_msg"); data->remaining_time = (GtkWidget*) gtk_builder_get_object (builder, "remaining_time"); data->bold_tag = gtk_text_tag_new ("bold"); g_object_set (data->bold_tag, "weight", PANGO_WEIGHT_BOLD, NULL); gtk_text_tag_table_add (tag_table, data->bold_tag); data->error_buf = gtk_text_buffer_new (tag_table); g_object_unref (tag_table); gtk_text_view_set_buffer (GTK_TEXT_VIEW (data->error_msg), data->error_buf); g_object_unref (builder); // set the src label if (data->job->srcs) { GList *l = fm_list_peek_head_link (data->job->srcs); int i; char *disp; FmPath *path; GString *str = g_string_sized_new (512); path = FM_PATH (l->data); disp = fm_path_display_basename (path); g_string_assign (str, disp); g_free (disp); for ( i =1, l=l->next; i < 10 && l; l=l->next, ++i) { path = FM_PATH (l->data); g_string_append (str, _(", ")); disp = fm_path_display_basename (path); g_string_append (str, disp); g_free (disp); } if (l) g_string_append (str, "..."); gtk_label_set_text (GTK_LABEL (data->src), str->str); g_string_free (str, TRUE); } // FIXME_pcm: use accessor functions instead switch (data->job->type) { case FM_FILE_OP_MOVE: title = _("Moving files"); break; case FM_FILE_OP_COPY: title = _("Copying files"); break; case FM_FILE_OP_TRASH: title = _("Trashing files"); break; case FM_FILE_OP_DELETE: title = _("Deleting files"); break; case FM_FILE_OP_LINK: title = _("Creating symlinks"); break; case FM_FILE_OP_CHANGE_ATTR: title = _("Changing file attributes"); break; } if (title) { gtk_window_set_title (GTK_WINDOW (data->dlg), title); gtk_label_set_text (GTK_LABEL (data->act), title); } if (dest = fm_file_ops_job_get_dest (data->job)) { char *dest_str = fm_path_display_name (dest, TRUE); gtk_label_set_text (GTK_LABEL (to), dest_str); g_free (dest_str); } else { gtk_widget_destroy (data->dest); gtk_widget_destroy (to_label); } gtk_window_present (GTK_WINDOW (data->dlg)); data->update_timeout = g_timeout_add (500, (GSourceFunc)on_update_dlg, data); data->delay_timeout = 0; return FALSE; }
// FIXME_pcm: this is too dirty. Need some refactor later. static void update_permissions (FmFilePropData *data) { FmFileInfo *file_info = (FmFileInfo*)fm_list_peek_head (data->files); GList *l; int sel; char *tmp; mode_t owner_perm = (file_info->mode & S_IRWXU); mode_t group_perm = (file_info->mode & S_IRWXG); mode_t other_perm = (file_info->mode & S_IRWXO); mode_t exec_perm = (file_info->mode & (S_IXUSR|S_IXGRP|S_IXOTH)); uid_t uid = file_info->uid; gid_t gid = file_info->gid; struct group *grp = NULL; struct passwd *pw = NULL; data->all_native = fm_path_is_native (fm_file_info_get_path (file_info)); data->has_dir = S_ISDIR (file_info->mode) != FALSE; for (l=fm_list_peek_head_link (data->files)->next; l; l=l->next) { FmFileInfo *file_info = (FmFileInfo*)l->data; if ( !fm_path_is_native (fm_file_info_get_path (file_info)) ) data->all_native = FALSE; if (S_ISDIR (file_info->mode)) data->has_dir = TRUE; if ( uid != file_info->uid ) uid = -1; if ( gid != file_info->gid ) gid = -1; if ( owner_perm != -1 && owner_perm != (file_info->mode & S_IRWXU) ) owner_perm = -1; if ( group_perm != -1 && group_perm != (file_info->mode & S_IRWXG) ) group_perm = -1; if ( other_perm != -1 && other_perm != (file_info->mode & S_IRWXO) ) other_perm = -1; if ( exec_perm != (file_info->mode & (S_IXUSR|S_IXGRP|S_IXOTH)) ) exec_perm = -1; } if ( data->all_native ) { if ( uid >= 0 ) { pw = getpwuid (uid); if (pw) gtk_entry_set_text (GTK_ENTRY (data->owner), pw->pw_name); } if ( gid >= 0 ) { grp = getgrgid (gid); if (grp) gtk_entry_set_text (GTK_ENTRY (data->group), grp->gr_name); } } if ( uid >=0 && !pw ) { tmp = g_strdup_printf ("%u", uid); gtk_entry_set_text (GTK_ENTRY (data->owner), tmp); g_free (tmp); } if ( gid >=0 && !grp ) { tmp = g_strdup_printf ("%u", gid); gtk_entry_set_text (GTK_ENTRY (data->group), tmp); g_free (tmp); } data->orig_owner = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->owner))); data->orig_group = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->group))); // on local filesystems, only root can do chown. if ( data->all_native && geteuid () != 0 ) { gtk_editable_set_editable (GTK_EDITABLE (data->owner), FALSE); gtk_editable_set_editable (GTK_EDITABLE (data->group), FALSE); } sel = NO_CHANGE; if (owner_perm != -1) { if ( (owner_perm & (S_IRUSR|S_IWUSR)) == (S_IRUSR|S_IWUSR) ) sel = READ_WRITE; else if ( (owner_perm & (S_IRUSR|S_IWUSR)) == S_IRUSR ) sel = READ_ONLY; else if ( (owner_perm & (S_IRUSR|S_IWUSR)) == S_IWUSR ) sel = WRITE_ONLY; else sel = NONE; } gtk_combo_box_set_active (GTK_COMBO_BOX (data->owner_perm), sel); data->owner_perm_sel = sel; sel = NO_CHANGE; if (group_perm != -1) { if ( (group_perm & (S_IRGRP|S_IWGRP)) == (S_IRGRP|S_IWGRP) ) sel = READ_WRITE; else if ( (group_perm & (S_IRGRP|S_IWGRP)) == S_IRGRP ) sel = READ_ONLY; else if ( (group_perm & (S_IRGRP|S_IWGRP)) == S_IWGRP ) sel = WRITE_ONLY; else sel = NONE; } gtk_combo_box_set_active (GTK_COMBO_BOX (data->group_perm), sel); data->group_perm_sel = sel; sel = NO_CHANGE; if (other_perm != -1) { if ( (other_perm & (S_IROTH|S_IWOTH)) == (S_IROTH|S_IWOTH) ) sel = READ_WRITE; else if ( (other_perm & (S_IROTH|S_IWOTH)) == S_IROTH ) sel = READ_ONLY; else if ( (other_perm & (S_IROTH|S_IWOTH)) == S_IWOTH ) sel = WRITE_ONLY; else sel = NONE; } gtk_combo_box_set_active (GTK_COMBO_BOX (data->other_perm), sel); data->other_perm_sel = sel; if (data->has_dir) gtk_widget_hide ( data->exec ); if ( exec_perm != -1 ) { gboolean xusr = (exec_perm & S_IXUSR) != 0; gboolean xgrp = (exec_perm & S_IXGRP) != 0; gboolean xoth = (exec_perm & S_IXOTH) != 0; if ( xusr == xgrp && xusr == xoth ) // executable { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->exec), xusr); data->exec_state = xusr; } else // inconsistent { gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->exec), TRUE); g_signal_connect (data->exec, "toggled", G_CALLBACK (on_exec_toggled), data); data->exec_state = -1; } } else // inconsistent { gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (data->exec), TRUE); g_signal_connect (data->exec, "toggled", G_CALLBACK (on_exec_toggled), data); data->exec_state = -1; } }
/********************************************************************* * ... * * ********************************************************************/ gboolean fm_file_info_job_run (FmJob *fmjob) { FmFileInfoJob *job = (FmFileInfoJob*) fmjob; GError *err = NULL; GList *l; for (l = fm_list_peek_head_link (job->file_infos); !fm_job_is_cancelled (fmjob) && l; ) { FmFileInfo *file_info = (FmFileInfo*) l->data; GList *next = l->next; job->current = file_info->path; if (fm_path_is_native (file_info->path)) { char *path_str = fm_path_to_str (file_info->path); // FileInfo rework: new function for testing... // this one is not cancellable and doesn't handle errors... // if (!fm_file_info_job_get_info_for_native_file (FM_JOB (job), file_info, path_str, &err)) if (!fm_file_info_set_for_native_file (file_info, path_str)) { //~ FmJobErrorAction act = fm_job_emit_error (FM_JOB(job), err, FM_JOB_ERROR_MILD); //~ //~ g_error_free (err); //~ err = NULL; //~ //~ if (act == FM_JOB_RETRY) //~ continue; DEBUG ("fm_file_info_set_for_native_file: error reading %s\n", path_str); next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_free (path_str); } else { GFile *gf; if (fm_path_is_virtual (file_info->path)) { // This is a xdg menu if (fm_path_is_xdg_menu (file_info->path)) { MenuCache *mc; MenuCacheDir *dir; char *path_str = fm_path_to_str (file_info->path); char *menu_name = path_str + 5, ch; char *dir_name; while (*menu_name == '/') ++menu_name; dir_name = menu_name; while (*dir_name && *dir_name != '/') ++dir_name; ch = *dir_name; *dir_name = '\0'; menu_name = g_strconcat (menu_name, ".menu", NULL); mc = menu_cache_lookup_sync (menu_name); g_free (menu_name); if (*dir_name && !(*dir_name == '/' && dir_name[1] == '\0')) { char *tmp = g_strconcat ("/", menu_cache_item_get_id (MENU_CACHE_ITEM(menu_cache_get_root_dir (mc))), dir_name, NULL); dir = menu_cache_get_dir_from_path (mc, tmp); g_free (tmp); } else { dir = menu_cache_get_root_dir (mc); } if (dir) { fm_file_info_set_from_menu_cache_item (file_info, (MenuCacheItem*) dir); } else { next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_free (path_str); menu_cache_unref (mc); l = l->next; continue; } } gf = fm_path_to_gfile (file_info->path); if (!fm_file_info_job_get_info_for_gfile (FM_JOB (job), file_info, gf, &err)) { FmJobErrorAction act = fm_job_emit_error (FM_JOB (job), err, FM_JOB_ERROR_MILD); g_error_free (err); err = NULL; if (act == FM_JOB_RETRY) continue; next = l->next; fm_list_delete_link (job->file_infos, l); // Also calls unref... } g_object_unref (gf); } l = next; } return TRUE; }
static void on_folder_view_sel_changed(FmFolderView* fv, FmFileInfoList* files, FmTabPage* page) { char* msg = page->status_text[FM_STATUS_TEXT_SELECTED_FILES]; g_free(msg); msg = NULL; // use SI metric by default static gboolean use_si_prefix = TRUE ; unsigned items_num = 0; if (files) items_num = fm_list_get_length(files) ; if (items_num > 1) // multiple items are selected { goffset items_totalsize = 0 ; // whether selected items contain dir gboolean items_contain_dir = FALSE ; GList* l; for (l=fm_list_peek_head_link(files);l;l=l->next) { FmFileInfo* fi = (FmFileInfo*)l->data; // ignore dir when calculating total size. because that // may take a long long time, not suitable for updating // statusbar in real time. if (fm_file_info_is_dir(fi) ) { items_contain_dir = TRUE; } else { // Non-dir items are regard as files // Should extra logic be added for different kinds of files? // hardlink, symlink, pipe, socket ? items_totalsize += fm_file_info_get_size(fi) ; } } // when the selected items contain dir, do not show size info on the // statusbar, because the calculated total size counts for files only // and showing it would be misleading to the user. if (items_contain_dir) { msg = g_strdup_printf("%d items selected", items_num); } else { char items_totalsize_str[ 64 ]; fm_file_size_to_str( items_totalsize_str, items_totalsize, use_si_prefix ); msg = g_strdup_printf("%d items selected, total size: %s", \ items_num, items_totalsize_str); } } else if (items_num == 1) { FmFileInfo* fi = fm_list_peek_head(files); const char* size_str = fm_file_info_get_disp_size(fi); gboolean is_link = fm_file_info_is_symlink(fi); if (is_link && size_str) { msg = g_strdup_printf("\"%s\" link to \"%s\" (%s)", fm_file_info_get_disp_name(fi), fm_file_info_get_target(fi), size_str); } else if (is_link) { msg = g_strdup_printf("\"%s\" link to \"%s\"", fm_file_info_get_disp_name(fi), fm_file_info_get_target(fi)); } else if (size_str) { msg = g_strdup_printf("\"%s\" (%s) %s", fm_file_info_get_disp_name(fi), size_str, fm_file_info_get_desc(fi)); } else { msg = g_strdup_printf("\"%s\" %s", fm_file_info_get_disp_name(fi), fm_file_info_get_desc(fi)); } } page->status_text[FM_STATUS_TEXT_SELECTED_FILES] = msg; g_signal_emit(page, signals[STATUS], 0, (guint)FM_STATUS_TEXT_SELECTED_FILES, msg); }