/* * myfc_gtk.c - multiple file chooser * Copyright (C) 2005 Lee Bigelow * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include"myfc_gtk.h" void myfc_add_foreach_func(gchar *fpath, GtkListStore *myfc_ls) { GtkTreeIter iter; gchar *icon = GTK_STOCK_FILE; gchar *fdisp; fdisp = g_filename_display_name(fpath); if ( g_file_test(fpath, G_FILE_TEST_IS_DIR) == TRUE ) { icon = GTK_STOCK_DIRECTORY; } gtk_list_store_append(myfc_ls, &iter); gtk_list_store_set(myfc_ls, &iter, COL_ICON, icon, COL_FILE, fpath, COL_DFILE, fdisp, -1); g_free(fdisp); } void myfc_add_cb(GtkWidget *widget, MyfcData *myfcd) { GSList *selfiles; selfiles = gtk_file_chooser_get_filenames(myfcd->fc); g_slist_foreach(selfiles, (GFunc) myfc_add_foreach_func, myfcd->ls); } void myfc_onDragDataReceived(GtkWidget *widget, GdkDragContext *context, int x, int y, GtkSelectionData *seldata, guint info, guint time, gpointer userdata) { GtkListStore *myfc_ls; gchar **uri_list; gchar *hostname; gchar *filename; gint i; myfc_ls = GTK_LIST_STORE(userdata); uri_list = gtk_selection_data_get_uris(seldata); for(i=0; uri_list[i] != NULL; i++) { filename = g_filename_from_uri(uri_list[i], &hostname, NULL); printf("\nhost: %s\npath: %s\n", hostname, filename); if ( filename != NULL && g_file_test(filename, G_FILE_TEST_EXISTS) ) myfc_add_foreach_func(filename, myfc_ls); g_free(filename); } g_strfreev(uri_list); } void myfc_remove_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list) { GtkTreeRowReference *rowref; rowref = gtk_tree_row_reference_new(model, path); *rowref_list = g_list_append(*rowref_list, rowref); } void myfc_remove_cb(GtkWidget *widget, MyfcData *myfcd) { GtkTreeSelection *sel; GtkTreePath *path; GtkTreeIter iter; GList *rr_list = NULL; /* row ref list of selected rows */ GList *node; sel = gtk_tree_view_get_selection(myfcd->tv); gtk_tree_selection_selected_foreach(sel, (GtkTreeSelectionForeachFunc) myfc_remove_foreach_func, &rr_list); for (node = rr_list; node != NULL; node = node->next) { path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); if (path) { if ( gtk_tree_model_get_iter(GTK_TREE_MODEL(myfcd->ls), &iter, path) ) { gtk_list_store_remove(myfcd->ls, &iter); } gtk_tree_path_free(path); } } g_list_foreach(rr_list, (GFunc) gtk_tree_row_reference_free, NULL); g_list_free(rr_list); } GtkListStore * make_myfc_ls(void) { GtkListStore *liststore; /* store holds (icon, fpath, fdisp) */ liststore = gtk_list_store_new(3, GTK_TYPE_STRING, GTK_TYPE_STRING, GTK_TYPE_STRING); return liststore; } GtkWidget * make_myfc_tree(GtkListStore *myfc_ls) { GtkTreeView *treeview; GtkTreeSelection *sel; GtkTreeViewColumn *tvcol; GtkCellRenderer *renderer; enum { TARGET_URI }; GtkTargetEntry targetentries[] = { { "text/uri-list", 0, TARGET_URI }, }; treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(myfc_ls))); gtk_tree_view_set_rules_hint(treeview, TRUE); /* make treeview use multiple selections */ sel = gtk_tree_view_get_selection(treeview); gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE); /* create treeview column */ tvcol = gtk_tree_view_column_new(); /* filepath icon renderer*/ renderer = gtk_cell_renderer_pixbuf_new(); gtk_tree_view_column_pack_start(tvcol, renderer, FALSE); gtk_tree_view_column_add_attribute(tvcol, renderer, "stock-id", COL_ICON); /* filepath text renderer*/ renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(tvcol, renderer, TRUE); gtk_tree_view_column_add_attribute(tvcol, renderer, "text", COL_DFILE); gtk_tree_view_column_set_title(tvcol, "File and directories to add:"); /* append column to treeview */ gtk_tree_view_append_column(treeview, tvcol); /* setup drag and drop attributes */ gtk_drag_dest_set(GTK_WIDGET(treeview), GTK_DEST_DEFAULT_ALL, targetentries, 1, GDK_ACTION_COPY|GDK_ACTION_MOVE); g_signal_connect(GTK_WIDGET(treeview), "drag_data_received", G_CALLBACK(myfc_onDragDataReceived), myfc_ls); return GTK_WIDGET(treeview); } gboolean view_popup_menu(GtkWidget *treeview, GdkEventButton *event, MyfcData *myfcd) { GtkWidget *menu, *menuitem; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { menu = gtk_menu_new(); menuitem = gtk_menu_item_new_with_label("Remove Selected From List"); g_signal_connect(menuitem, "activate", (GCallback) myfc_remove_cb, myfcd); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event)); return TRUE; } return FALSE; } GtkDialog * make_myfc(gchar *archive, GtkListStore *myfc_ls) { static MyfcData myfcd; GtkDialog *dialog; GtkWidget *vpaned, *vbox, *hbox, *label, *button, *image, *scrollw; GtkTooltips *button_tips; myfcd.ls = myfc_ls; button_tips = gtk_tooltips_new(); /* make general dialog box */ dialog = GTK_DIALOG( gtk_dialog_new_with_buttons( "Select Files or Directories To Add", NULL, GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL) ); gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT, GTK_RESPONSE_CANCEL, -1); /* pack panes into dialog vbox */ vpaned = gtk_vpaned_new(); gtk_container_add(GTK_CONTAINER(dialog->vbox), vpaned); gtk_widget_show(vpaned); /* pack file chooser into top pane */ myfcd.fc = GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN) ); gtk_paned_pack1(GTK_PANED(vpaned), GTK_WIDGET(myfcd.fc), TRUE, TRUE); gtk_widget_show(GTK_WIDGET(myfcd.fc)); gtk_widget_set_size_request(GTK_WIDGET(myfcd.fc), 450, 200); gtk_file_chooser_set_select_multiple(myfcd.fc, TRUE); /* pack vbox of treeview into bottom pane */ vbox = gtk_vbox_new(FALSE, 0); gtk_widget_set_size_request(vbox, 450, 180); gtk_widget_show (vbox); gtk_paned_pack2(GTK_PANED(vpaned), GTK_WIDGET(vbox), TRUE, TRUE); /* hbox for buttons goes in top of vbox */ hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE,FALSE, 0); /* label packs into start of hbox */ label = gtk_label_new(archive); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 5); gtk_widget_show(label); gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START); /* remove button packs into end of hbox */ button = gtk_button_new_with_mnemonic("Remove _From list"); gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(myfc_remove_cb), &myfcd); image = gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_tooltips_set_tip(button_tips, button, "(ALT-F) Remove selected files from the \"add to archive\" list below.", NULL); /* add button packs into end of hbox */ button = gtk_button_new_with_mnemonic("Add _To list"); gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(myfc_add_cb), &myfcd); image = gtk_image_new_from_stock(GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_tooltips_set_tip(button_tips, button, "(ALT-T) Add selected files from the \"file chooser\" above to the \"add to archive\" list below.", NULL); /* next scroll window packs in vbox */ scrollw = gtk_scrolled_window_new(NULL, NULL); gtk_box_pack_start(GTK_BOX(vbox), scrollw, TRUE, TRUE, 0); gtk_widget_show(scrollw); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); /* finally the treeview packs into the scrollw */ myfcd.tv = GTK_TREE_VIEW(make_myfc_tree(myfc_ls)); gtk_container_add(GTK_CONTAINER(scrollw), GTK_WIDGET(myfcd.tv)); gtk_widget_show(GTK_WIDGET(myfcd.tv)); g_signal_connect(GTK_WIDGET(myfcd.tv), "button_press_event", (GCallback) view_popup_menu, &myfcd); return dialog; }