2 * Handle console GUI selection of files
3 * Kern Sibbald, March, 2004
13 extern BSOCK *UA_sock;
14 void write_director(const gchar *msg);
15 void start_director_reader(gpointer data);
16 void stop_director_reader(gpointer data);
19 /* Forward referenced subroutines */
20 void FillDirectory(const char *path, Window *window);
22 static void click_column_cb(GtkCList *item, gint column, Window *restore);
23 static void select_row_cb(GtkCList *item, gint row, gint column,
24 GdkEventButton *event, Window *restore);
25 void row_data_destroy_cb(gpointer data);
26 void split_path_and_filename(const char *fname, POOLMEM **path, int *pnl,
27 POOLMEM **file, int *fnl);
30 static GdkPixmap *check_pixmap = NULL;
31 static GdkPixmap *check_trans = NULL;
32 static GdkPixmap *blank_pixmap = NULL;
33 static GdkPixmap *blank_trans = NULL;
36 static GtkWidget *restore_dir; /* current directory edit box */
37 static GtkWidget *scrolled; /* select files scrolled window */
38 static Window *restore;
40 const int NUM_COLUMNS = 7;
41 const int CHECK_COLUMN = 0;
42 const int FILE_COLUMN = 1;
43 const int MODES_COLUMN = 2;
44 const int DATE_COLUMN = 6;
48 * Read Director output and discard it until next prompt
50 static void discard_to_prompt()
52 while (bnet_recv(UA_sock) > 0) {
53 set_text(UA_sock->msg, UA_sock->msglen);
58 * Move up one directory
61 on_restore_up_button_clicked(GtkButton *button, gpointer user_data)
63 split_path_and_filename(restore->fname, &restore->path, &restore->pnl,
64 &restore->file, &restore->fnl);
65 FillDirectory(restore->path, restore);
68 static void mark_row(int row, bool mark)
74 gtk_clist_get_text(restore->list, row, FILE_COLUMN, &file);
76 bstrncpy(new_mark, "x", sizeof(new_mark));
77 len = Mmsg(&restore->buf, "mark %s", file);
79 bstrncpy(new_mark, " ", sizeof(new_mark));
80 len = Mmsg(&restore->buf, "unmark %s", file);
82 gtk_clist_set_text(restore->list, row, CHECK_COLUMN, new_mark);
83 /* strip trailing slash from directory name */
84 while (len > 1 && restore->buf[len-1] == '/') {
85 restore->buf[len-1] = 0;
87 write_director(restore->buf);
92 on_restore_add_button_clicked(GtkButton *button, gpointer user_data)
94 int num_selected = g_list_length(restore->list->selection);
97 for (int i=0; i < num_selected; i++) {
98 row = (int)(long int)g_list_nth_data(restore->list->selection, i);
105 on_restore_remove_button_clicked(GtkButton *button, gpointer user_data)
107 int num_selected = g_list_length(restore->list->selection);
110 for (int i=0; i < num_selected; i++) {
111 row = (int)(long int)g_list_nth_data(restore->list->selection, i);
112 mark_row(row, false);
117 * Called once at the beginning of the program for setup
119 void select_restore_setup()
121 const gchar *title[NUM_COLUMNS] = {_("Mark"), _("File"), _("Mode"), _("User"), _("Group"), _("Size"), _("Date")};
123 restore_file_selection = create_restore_file_selection();
124 if (!restore_file_selection) {
125 Dmsg0(000, "Restore_files not setup.\n");
127 restore_dir = lookup_widget(restore_file_selection, "restore_dir");
128 scrolled = lookup_widget(restore_file_selection, "scrolled");
130 Dmsg0(000, "Scrolled not setup.\n");
133 restore = new_window();
136 check_pixmap = gdk_pixmap_colormap_create_from_xpm(NULL,
137 gdk_colormap_get_system(), &check_trans, NULL,
139 blank_pixmap = gdk_pixmap_colormap_create_from_xpm(NULL,
140 gdk_colormap_get_system(), &blank_trans, NULL,
144 /* XXX: Stupid gtk_clist_set_selection_mode() has incorrect declaration of the title argument */
145 /* XXX: Workaround by typecast... peter@ifm.liu.se */
147 restore->list = (GtkCList *)gtk_clist_new_with_titles(NUM_COLUMNS, (gchar **) title);
148 gtk_clist_set_selection_mode(restore->list, GTK_SELECTION_EXTENDED);
149 gtk_clist_set_sort_column(restore->list, FILE_COLUMN);
150 gtk_clist_set_auto_sort(restore->list, true);
151 gtk_signal_connect(GTK_OBJECT(restore->list), "click_column",
152 G_CALLBACK(click_column_cb), restore);
153 gtk_signal_connect(GTK_OBJECT(restore->list), "select_row",
154 G_CALLBACK(select_row_cb), restore);
156 gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(restore->list));
157 restore->buf = get_pool_memory(PM_FNAME);
158 restore->fname = get_pool_memory(PM_FNAME);
159 restore->path = get_pool_memory(PM_NAME);
160 restore->file = get_pool_memory(PM_NAME);
164 * Select files dialog called
166 void select_restore_files()
169 set_restore_dialog_defaults();
170 gtk_widget_show(GTK_WIDGET(restore->list));
171 FillDirectory("/", restore);
177 * Fill the CList box with files at path
179 void FillDirectory(const char *path, Window *restore)
181 char pathbuf[MAXSTRING];
182 char modes[20], user[20], group[20], size[20], date[30];
185 gchar *text[NUM_COLUMNS] = {marked, file, modes, user, group, size, date};
186 GtkCList *list = restore->list;
189 stop_director_reader(NULL);
190 pm_strcpy(&restore->fname, path);
191 gtk_entry_set_text(GTK_ENTRY(restore_dir), restore->fname);
192 gtk_clist_freeze(list);
193 gtk_clist_clear(list);
195 bsnprintf(pathbuf, sizeof(pathbuf), "cd %s", path);
196 Dmsg1(100, "%s\n", pathbuf);
197 write_director(pathbuf);
200 write_director("dir");
201 while (bnet_recv(UA_sock) > 0) {
202 char *p = UA_sock->msg;
204 strip_trailing_junk(UA_sock->msg);
208 Dmsg1(200, "Got: %s\n", p);
213 skip_nonspaces(&p); /* permissions */
215 bstrncpy(modes, l, sizeof(modes));
217 skip_nonspaces(&p); /* link count */
221 skip_nonspaces(&p); /* user */
224 bstrncpy(user, l, sizeof(user));
226 skip_nonspaces(&p); /* group */
228 bstrncpy(group, l, sizeof(group));
231 skip_nonspaces(&p); /* size */
233 bstrncpy(size, l, sizeof(size));
236 skip_nonspaces(&p); /* date/time */
240 bstrncpy(date, l, sizeof(date));
243 bstrncpy(marked, "x", sizeof(marked));
246 bstrncpy(marked, " ", sizeof(marked));
248 split_path_and_filename(p, &restore->path, &restore->pnl,
249 &restore->file, &restore->fnl);
251 // Dmsg1(000, "restore->fname=%s\n", restore->fname);
252 bstrncpy(file, restore->file, sizeof(file));
253 // printf("modes=%s user=%s group=%s size=%s date=%s file=%s\n",
254 // modes, user, group, size, date, file);
256 gtk_clist_append(list, text);
261 /* Fix up length of file column */
262 gtk_clist_set_column_width(list, FILE_COLUMN, gtk_clist_optimal_column_width(list, FILE_COLUMN));
263 gtk_clist_set_column_width(list, MODES_COLUMN, gtk_clist_optimal_column_width(list, MODES_COLUMN));
264 gtk_clist_thaw(list);
265 start_director_reader(NULL);
270 Window *window = (Window *)malloc(sizeof(Window));
271 memset(window, 0, sizeof(window));
277 * User clicked a column title
279 static void click_column_cb(GtkCList *item, gint column, Window *restore)
284 * User selected a row
286 static void select_row_cb(GtkCList *item, gint row, gint column,
287 GdkEventButton *event, Window *restore)
291 /* Column non-negative => double click */
293 gtk_clist_unselect_row(item, row, column);
294 /* Double click on column 0 means to mark or unmark */
296 gtk_clist_get_text(restore->list, row, CHECK_COLUMN, &marked);
297 Dmsg1(200, "Marked=%s\n", marked);
298 if (!marked || strcmp(marked, "x") != 0) {
301 mark_row(row, false);
304 /* Double clicking on directory means to move to it */
306 gtk_clist_get_text(item, row, FILE_COLUMN, &file);
308 if (len > 0 && file[len-1] == '/') {
309 /* Change to new directory */
310 pm_strcpy(restore->path, restore->fname);
312 Mmsg(restore->fname, "%s%s", restore->path, file+1);
314 Mmsg(restore->fname, "%s%s", restore->path, file);
316 FillDirectory(restore->fname, restore);
323 * CList row is being destroyed get rid of our data
325 void row_data_destroy_cb(gpointer data)
333 GdkPixmap *pixmap, *trans;
334 utf8_mark = g_locale_to_utf8(new_mark, -1, NULL, NULL, NULL);
335 gtk_clist_get_pixmap(restore->list, row, CHECK_COLUMN, &pixmap, &trans);
336 if (pixmap == blank_pixmap) {
337 bstrncpy(new_mark, "x", sizeof(new_mark));
338 // gtk_clist_set_pixmap(item, row, CHECK_COLUMN, check_pixmap, check_trans);
341 static void window_delete_cb(GtkWidget *item, GdkEvent *event, Window *restore)
343 gtk_widget_destroy(restore->window);
345 free_pool_memory(restore->buf);
346 free_pool_memory(restore->fname);
347 free_pool_memory(restore->path);
348 free_pool_memory(restore->file);
354 gtk_clist_set_pixmap(list, row, CHECK_COLUMN, check_pixmap, check_trans);
356 gtk_clist_set_pixmap(list, row, CHECK_COLUMN, blank_pixmap, blank_trans);