📄 menus.c
字号:
/* recursively remove all children of a node in a ctree */void ctree_remove_children(GtkCTree * tree, GtkCTreeNode * node) {GtkCTreeNode *child;GList *sibling_list;gchar *strpnt; /* Get the child node and make sure it's not NULL. */ child = GTK_CTREE_ROW (node)->children; if (child == NULL) return; /* Get the list of siblings. */ sibling_list = NULL; for (; child; child = GTK_CTREE_ROW (child)->sibling) sibling_list = g_list_append (sibling_list, child); /* break out from recusion */ if (sibling_list == NULL) return; /* Remove all of the sibling nodes. */ gtk_clist_freeze (GTK_CLIST (tree)); for (; sibling_list; sibling_list = sibling_list->next) { /* go recursive */ ctree_remove_children(tree, GTK_CTREE_NODE(sibling_list->data)); /* free allocated node-data */ strpnt = gtk_ctree_node_get_row_data (tree, GTK_CTREE_NODE (sibling_list->data)); g_free(strpnt); gtk_ctree_remove_node (tree, GTK_CTREE_NODE (sibling_list->data)); } gtk_clist_thaw (GTK_CLIST (tree)); /* Free up memory. */ g_list_free (g_list_first(sibling_list));}/* called when the users expands a directory in the ctree */gint ctree_expand (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {gchar *newdir;GdkCursor *normal_cursor, *clock_cursor;GdkWindowAttr *win_attr; /* fetch full path the node stands for */ newdir = gtk_ctree_node_get_row_data (tree, node); /* skip root-dir */ if (newdir == NULL) return TRUE; /* Change cursor to clock */ gdk_window_get_user_data (GTK_WIDGET (ctree_window)->window, (gpointer) &win_attr); /* Why does this cause a core dump? Bug in GTK I guess...workaround is to allocate a new cursor normal_cursor = win_attr->cursor; */ normal_cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW); clock_cursor = gdk_cursor_new (GDK_WATCH); gdk_window_set_cursor (GTK_WIDGET (ctree_window)->window, clock_cursor); /* gives gtk a break and time to update REALLY the cursor */ /* I dont think this slowes things down */ gtk_main_iteration_do(FALSE); gtk_clist_freeze (GTK_CLIST (tree)); /* remove first everything and then add new nodes */ ctree_remove_children(tree,node); ctree_add_dir_nodes(newdir,tree,node,ctree_showfiles); /* now scroll to position (OPTIONAL) */ /* gtk_ctree_node_moveto(tree,node,0,0.1,0); */ /* unfreeze and change cursor back */ gtk_clist_thaw (GTK_CLIST (tree)); normal_cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW); gdk_window_set_cursor (GTK_WIDGET (ctree_window)->window, normal_cursor); return TRUE;}/* called when the user selects a row in a ctree */gint ctree_select_row (GtkCTree *tree, GtkCTreeNode *node, gpointer data) {gchar *pnt; pnt = gtk_ctree_node_get_row_data (tree, node); if (pnt == NULL) { /* no path set */ gtk_entry_set_text(GTK_ENTRY(ctree_entry),""); if (ctree_okbutton) gtk_widget_set_sensitive(ctree_okbutton,FALSE); } else { gtk_entry_set_text(GTK_ENTRY(ctree_entry),pnt); if (ctree_okbutton) gtk_widget_set_sensitive(ctree_okbutton,TRUE); } return TRUE;}/* frees the ctree from memory */void ctree_cleanup() { ctree_remove_children(ctree_base,parent_node); gtk_ctree_collapse_recursive(ctree_base, parent_node);}/* can be used to change the view mode (dirs only or with files) *//* will collaps the tree to its base mode */void ctree_change_viewmode(gint showfiles) { /* do nothing if the state is the same */ if (showfiles == ctree_showfiles) return; ctree_showfiles = showfiles; /* collapse whole tree to ensure correct redraw */ ctree_remove_children(ctree_base,parent_node); gtk_ctree_collapse_recursive(ctree_base, parent_node); /* now redraw with correct setting */ ctree_add_dir_nodes(ctree_basedir,ctree_base,parent_node,ctree_showfiles); gtk_ctree_expand(ctree_base,parent_node);}/* search current branch of ctree for a certain string */GtkCTreeNode *ctree_search_nodes(GtkCTree *tree, GtkCTreeNode *node, gchar *cmpstr) {GtkCTreeNode *child;GList *sibling_list;gchar *strpnt; /* Get the child node and make sure it's not NULL. */ child = GTK_CTREE_ROW (node)->children; if (child == NULL) return NULL; /* Get the list of siblings. */ sibling_list = NULL; for (; child; child = GTK_CTREE_ROW (child)->sibling) sibling_list = g_list_append (sibling_list, child); for (; sibling_list; sibling_list = sibling_list->next) { /* get data entry */ child = GTK_CTREE_NODE (sibling_list->data); strpnt = gtk_ctree_node_get_row_data (tree, child); if (strpnt && (strcmp(strpnt,cmpstr) == 0)) { g_list_free (g_list_first(sibling_list)); return child; } } /* nothing found */ g_list_free (g_list_first(sibling_list)); return NULL;}/* interprets a manual entered path and adopts the tree-listing */void ctree_expand_manualpath(GtkWidget* entry) {gchar *p1;gchar path[MAXLINE];gchar tmp[MAXLINE];gchar tmp2[MAXLINE];GtkCTreeNode *sibling, *node; strncpy(path,gtk_entry_get_text(GTK_ENTRY(entry)),MAXLINE); /* must begin with a slash */ if (path[0] != '/') return; if (strlen(path) > MAXLINE) return; /* walk through directory tree as if user clicked */ sibling = parent_node; strcpy(tmp,path); strcpy(tmp2,""); p1 = strtok(tmp,"/"); while (p1) { strcat(tmp2,"/"); strcat(tmp2,p1); /* now look in current sibling for a matching string */ node = ctree_search_nodes(ctree_base, sibling, tmp2); /* something found? */ if (node) { /* now expand this node if possible */ ctree_expand(ctree_base, node, NULL); gtk_ctree_expand(ctree_base,node); gtk_ctree_select(ctree_base,node); /* now scroll to position */ gtk_ctree_node_moveto(ctree_base,node,0,0.1,0); /* prepare next level */ sibling = node; } p1 = strtok(NULL,"/"); } /* restore entry string */ gtk_entry_set_text(GTK_ENTRY(entry),path);}/* creates a ctree for directory browsing */ GtkCTree *create_directory_ctree(gchar *basedir,gchar *title, GtkWidget *win, GtkWidget *entry, gint showfiles) {gchar tmp[MAXLINE];GtkCTree *ctree;GtkCTreeNode *parent;gchar *titles[1];gchar *text[1];GtkStyle *style; /* save the parent window for cursor handling */ ctree_window = win; ctree_entry = entry; ctree_showfiles = showfiles; ctree_basedir = basedir; /* do we want a title? */ if (title == NULL) { ctree = GTK_CTREE (gtk_ctree_new (1, 0)); } else { titles[0] = title; ctree = GTK_CTREE (gtk_ctree_new_with_titles (1, 0, titles)); } ctree_base = ctree; gtk_clist_set_row_height(GTK_CLIST(ctree),tbf(16)); /* create folder pixmaps */ style = gtk_widget_get_style(GTK_WIDGET(ctree)); pixmap1 = gdk_pixmap_create_from_xpm_d(win->window, &mask1,&style->bg[GTK_STATE_NORMAL], (gchar **) treefolderclosed_xpm); pixmap2 = gdk_pixmap_create_from_xpm_d(win->window, &mask2,&style->bg[GTK_STATE_NORMAL], (gchar **) treefolderopen_xpm); pixmap3 = gdk_pixmap_create_from_xpm_d(win->window, &mask3,&style->bg[GTK_STATE_NORMAL], (gchar **) filesmall_xpm); /* connect our signal stuff */ gtk_signal_connect(GTK_OBJECT(ctree),"tree_expand", GTK_SIGNAL_FUNC(ctree_expand),NULL); gtk_signal_connect(GTK_OBJECT(ctree),"tree_select_row", GTK_SIGNAL_FUNC(ctree_select_row),NULL); /* make root entry in clist */ strcpy(tmp,basedir); text[0]=tmp; parent = gtk_ctree_insert_node (ctree,NULL, NULL,text,3,pixmap1,mask1,pixmap2,mask2,FALSE,TRUE); gtk_ctree_node_set_row_data(ctree,parent,g_strdup(basedir)); parent_node = parent; ctree_add_dir_nodes(basedir,ctree,parent,ctree_showfiles); return ctree;}void show_dir_btn_press(GtkWidget *widget, gpointer data) { dialog_done = GPOINTER_TO_INT(data);}/* popup a modal window, set cursor to watch, return path or NULL-string when cancel or delete_event found. Centers automatically above the toplevel-widow */void show_dir_tree(gchar *retvalue) {GtkWidget *dialog;GtkWidget *button1;GtkWidget *button2;GtkWidget *box1,*box2,*box3;GtkWidget *entry1,*b1_sep;GtkWidget *scrolled_win;GtkCTree *ctree;gint xpos, ypos;gint xsize, ysize;GdkCursor *cursor,*normal_cursor;GtkRequisition rq;GdkWindowAttr *win_attr; /* if another dialog is running, ignore */ if (dialog_done == 999) { return; } dodebug(8, "displaying show_dir_tree\n"); /* mark our dialog as running */ dialog_done = 999; /* create new window and position it relative to the main window */ dialog = gtk_window_new(GTK_WINDOW_DIALOG); gtk_window_set_title(GTK_WINDOW(dialog),text(2)); gtk_widget_set_usize(dialog,tbf(350),tbf(300)); /* make sure our window is always on top */ gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(toplevel)); gtk_signal_connect (GTK_OBJECT (dialog), "delete_event", GTK_SIGNAL_FUNC (dialog_delete_event), (gpointer) dialog); /* create layout for dialog */ box1 = gtk_vbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(dialog),box1); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(box1),scrolled_win,TRUE,TRUE,0); gtk_widget_realize(scrolled_win); gtk_widget_show(scrolled_win); box3 = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box3,FALSE,TRUE,10); entry1 = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(entry1),FALSE); gtk_box_pack_start(GTK_BOX(box3),entry1,TRUE,TRUE,10); gtk_widget_show(entry1); ctree = create_directory_ctree("/",text(84),dialog,entry1,0); gtk_clist_set_column_auto_resize(GTK_CLIST(ctree),0,TRUE); gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree)); gtk_widget_show( GTK_WIDGET (ctree)); gtk_widget_show(box3); gtk_widget_show(box1); b1_sep = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1),b1_sep,FALSE,TRUE,0); gtk_widget_show(b1_sep); box2 = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,TRUE,10); gtk_widget_show(box2); button1 = gtk_button_new_with_label(T_OK); ctree_okbutton = button1; gtk_box_pack_start(GTK_BOX(box2),button1,TRUE,TRUE,10); gtk_widget_show(button1); GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); gtk_widget_set_sensitive(button1,FALSE); gtk_signal_connect(GTK_OBJECT(button1),"clicked", GTK_SIGNAL_FUNC(show_dir_btn_press), GINT_TO_POINTER(0)); button2 = gtk_button_new_with_label(T_CANCEL); gtk_box_pack_start(GTK_BOX(box2),button2,TRUE,TRUE,10); gtk_widget_show(button2); GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); gtk_widget_grab_default (button2); gtk_signal_connect(GTK_OBJECT(button2),"clicked", GTK_SIGNAL_FUNC(show_dir_btn_press), GINT_TO_POINTER(-1)); /* grab cursor and change to watch */ gtk_grab_add(dialog); gdk_window_get_user_data(GTK_WIDGET(toplevel)->window, (gpointer) &win_attr); normal_cursor = win_attr->cursor; cursor = gdk_cursor_new(GDK_WATCH); gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,cursor); /* only center window when toplevel visible */ if ( GTK_WIDGET_VISIBLE(toplevel)) { gtk_window_position(GTK_WINDOW(dialog),GTK_WIN_POS_NONE); gdk_window_get_origin(GTK_WIDGET(toplevel)->window,&xpos,&ypos); gdk_window_get_size(GTK_WIDGET(toplevel)->window,&xsize,&ysize); gtk_widget_size_request(dialog,&rq); gtk_widget_set_uposition(GTK_WIDGET(dialog),xpos+xsize/2-rq.width/2,ypos+ysize/2-rq.height/2); } gtk_widget_show(dialog); /* now wait until button is pressed */ while (dialog_done == 999) { wait_and_process_events(); } gtk_grab_remove(GTK_WIDGET(dialog)); normal_cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW); gdk_window_set_cursor(GTK_WIDGET(toplevel)->window,normal_cursor); if (dialog_done != -1) { strcpy(retvalue,gtk_entry_get_text(GTK_ENTRY(entry1))); } else { /* cancel or delete_event */ strcpy(retvalue,""); } /* free ctree */ ctree_cleanup(); /* remove dialog window */ gtk_widget_destroy(dialog);}/* fileselector-box ok-button callback */void file_selector_ok(GtkWidget *widget, GtkFileSelection *fs) { dialog_done3 = 1;}/* display a file-selector box with defname preselected. Return "" or filename in retvalue */void show_file_selector(gchar *defname, gchar *retvalue) {GtkWidget *dialog;gint xpos, ypos;gint xsize, ysize;GdkCursor *cursor,*normal_cursor;GtkRequisition rq;GdkWindowAttr *win_attr;GtkButton *b1;GtkCList *dirs; /* if another dialog is running, ignore */ if (dialog_done3 == 999) { return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -