2
* $Id: search_cb.c,v 1.39 2004/01/15 23:51:48 wyldfire Exp $
4
* Copyright (c) 2001-2003, Raphael Manfredi, Richard Eckart
6
* GUI filtering functions.
8
*----------------------------------------------------------------------
9
* This file is part of gtk-gnutella.
11
* gtk-gnutella is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* gtk-gnutella is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with gtk-gnutella; if not, write to the Free Software
24
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
*----------------------------------------------------------------------
32
#include <gdk/gdkkeysyms.h>
34
#include "gtkcolumnchooser.h"
35
#include "search_cb.h"
36
#include "search_gui.h"
37
#include "statusbar_gui.h"
38
#include "override.h" /* Must be the last header included */
40
RCSID("$Id: search_cb.c,v 1.39 2004/01/15 23:51:48 wyldfire Exp $");
42
extern search_t *search_selected;
44
static gboolean in_autoselect = FALSE;
45
static gchar tmpstr[4096];
55
* Activates/deactivates buttons and popups based on what is selected
58
static void refresh_popup(void)
63
search = search_gui_get_current_search();
66
(NULL != (GTK_CLIST(search->ctree))->selection);
67
gtk_widget_set_sensitive
68
(lookup_widget(main_window, "button_search_download"), sensitive);
69
gtk_widget_set_sensitive
70
(lookup_widget(popup_search, "popup_search_drop_name"), sensitive);
71
gtk_widget_set_sensitive
72
(lookup_widget(popup_search, "popup_search_drop_sha1"), sensitive);
73
gtk_widget_set_sensitive
74
(lookup_widget(popup_search, "popup_search_drop_host"), sensitive);
75
gtk_widget_set_sensitive(
76
lookup_widget(popup_search, "popup_search_drop_name_global"),
78
gtk_widget_set_sensitive(
79
lookup_widget(popup_search, "popup_search_drop_sha1_global"),
81
gtk_widget_set_sensitive(
82
lookup_widget(popup_search, "popup_search_drop_host_global"),
84
gtk_widget_set_sensitive(
85
lookup_widget(popup_search, "popup_search_autodownload_name"),
87
gtk_widget_set_sensitive(
88
lookup_widget(popup_search, "popup_search_autodownload_sha1"),
90
gtk_widget_set_sensitive(
91
lookup_widget(popup_search, "popup_search_new_from_selected"),
94
gtk_widget_set_sensitive(
95
lookup_widget(popup_search, "popup_search_restart"), NULL != search);
96
gtk_widget_set_sensitive(
97
lookup_widget(popup_search, "popup_search_duplicate"), NULL != search);
100
gtk_widget_set_sensitive(
101
lookup_widget(popup_search, "popup_search_stop"),
102
!search_is_frozen(search->search_handle));
103
gtk_widget_set_sensitive(
104
lookup_widget(popup_search, "popup_search_resume"),
105
search_is_frozen(search->search_handle));
107
gtk_widget_set_sensitive(
108
lookup_widget(popup_search, "popup_search_restart"),
111
gtk_widget_set_sensitive(
112
lookup_widget(popup_search, "popup_search_stop"), FALSE);
113
gtk_widget_set_sensitive(
114
lookup_widget(popup_search, "popup_search_resume"), FALSE);
120
* search_cb_autoselect
122
* Autoselects all searches matching given node in given tree
123
* Uses the in_autosearch flag to prevent recursive autoselecting
125
gint search_cb_autoselect(GtkCTree *ctree, GtkCTreeNode *node,
126
gboolean search_autoselect_ident)
128
GtkCTreeNode *auto_node;
129
GtkCTreeNode *parent, *child;
132
guint32 fuzzy_threshold;
133
gboolean child_selected, node_expanded;
137
return 0; /* Prevent recursive autoselect */
139
in_autoselect = TRUE;
140
gnet_prop_get_guint32(PROP_FUZZY_THRESHOLD, &fuzzy_threshold, 0, 1);
143
* Rows with NULL data can appear when inserting new rows
144
* because the selection is resynced and the row data cannot
145
* be set until insertion (and therefore also selection syncing
149
rc = (record_t *) gtk_ctree_node_get_row_data(ctree, node);
150
gtk_clist_freeze(GTK_CLIST(ctree));
152
/* Search whole ctree for nodes to autoselect
154
for (x = 1, auto_node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
155
(NULL != auto_node) && (NULL != rc);
156
auto_node = GTK_CTREE_NODE_NEXT (auto_node)) {
158
if (NULL == auto_node)
161
rc2 = (record_t *) gtk_ctree_node_get_row_data(ctree, auto_node);
164
* Skip the line we selected in the first place.
170
g_warning(" on_ctree_search_results_select_row: "
171
"detected row with NULL data, skipping.");
175
parent = GTK_CTREE_NODE(auto_node);
176
row = GTK_CTREE_ROW(parent);
178
/* If auto_node is a child node, we skip it cause it will be handled
179
* when we come to it's parent
181
if(NULL != row->parent)
184
child = row->children;
185
if (NULL != child) /* If the node has children */
187
/* A header node. We expand it and check all of the children
188
* If one of the children get selected keep node expanded,
189
* if it was initially collapsed, collapse it again
191
child_selected = FALSE;
192
node_expanded = FALSE;
194
node_expanded = gtk_ctree_is_viewable(ctree, child);
195
gtk_ctree_expand(ctree, parent);
197
for (; NULL != child; row = GTK_CTREE_ROW(child),
198
child = row->sibling) {
200
rc2 = gtk_ctree_node_get_row_data (ctree, child);
205
if (search_autoselect_ident) {
206
if ((rc->size == rc2->size && rc->sha1 != NULL &&
208
memcmp(rc->sha1, rc2->sha1, SHA1_RAW_SIZE) == 0)
209
|| ((rc->sha1 == NULL) && (rc2->size == rc->size) &&
210
((!search_autoselect_fuzzy &&
211
!strcmp(rc2->name, rc->name)) ||
212
(search_autoselect_fuzzy &&
213
(fuzzy_compare(rc2->name, rc->name) * 100 >= (fuzzy_threshold << FUZZY_SHIFT)))
215
gtk_ctree_select(ctree, child);
216
child_selected = TRUE;
220
if (((rc->sha1 != NULL && rc2->sha1 != NULL &&
221
memcmp(rc->sha1, rc2->sha1, SHA1_RAW_SIZE) == 0) ||
222
(rc2 && !strcmp(rc2->name, rc->name))) &&
223
(rc2->size >= rc->size)) {
225
gtk_ctree_select(ctree, child);
226
child_selected = TRUE;
231
if ((!child_selected) && (!node_expanded))
232
gtk_ctree_collapse(ctree, parent);
235
/* Reget rc2 in case we overwrote it while parsing the children */
236
rc2 = (record_t *) gtk_ctree_node_get_row_data(ctree, auto_node);
238
if (search_autoselect_ident) {
241
* size check added to workaround buggy
242
* servents. -vidar, 2002-08-08
244
rc->size == rc2->size &&
245
rc->sha1 != NULL && rc2->sha1 != NULL &&
246
memcmp(rc->sha1, rc2->sha1, SHA1_RAW_SIZE) == 0
248
(rc->sha1 == NULL) &&
249
(rc2->size == rc->size) && (
250
(!search_autoselect_fuzzy &&
251
!strcmp(rc2->name, rc->name)) ||
252
(search_autoselect_fuzzy &&
253
(fuzzy_compare(rc2->name, rc->name) * 100 >= (fuzzy_threshold << FUZZY_SHIFT)))
257
gtk_ctree_select(ctree, auto_node);
262
if (((rc->sha1 != NULL && rc2->sha1 != NULL &&
263
memcmp(rc->sha1, rc2->sha1, SHA1_RAW_SIZE) == 0) ||
264
(rc2 && !strcmp(rc2->name, rc->name))) &&
265
(rc2->size >= rc->size)) {
267
gtk_ctree_select(ctree, auto_node);
273
gtk_clist_thaw(GTK_CLIST(ctree));
275
gtk_widget_queue_draw((GtkWidget *) ctree); /* Force redraw */
276
in_autoselect = FALSE;
286
void on_combo_entry_searches_activate
287
(GtkEditable *editable, gpointer user_data)
294
* on_search_popdown_switch
296
void on_search_popdown_switch(GtkWidget *w, gpointer data)
298
if (search_selected != NULL)
299
search_gui_set_current_search(search_selected);
304
* on_search_notebook_switch
306
* When the user switches notebook tabs, update the rest of GUI
308
* This may be obsolete as we removed the tabbed interface --Emile 27/12/03
310
void on_search_notebook_switch(GtkNotebook * notebook, GtkNotebookPage * page,
311
gint page_num, gpointer user_data)
315
sch = (search_t *) gtk_object_get_user_data(
316
GTK_OBJECT(gtk_notebook_get_nth_page(notebook, page_num)));
318
g_return_if_fail(sch);
320
search_gui_set_current_search(sch);
325
* on_clist_search_select_row
327
* Changes current search and updates GUI
329
void on_clist_search_select_row(GtkCList * clist, gint row, gint column,
330
GdkEvent * event, gpointer user_data)
334
g_assert(clist != NULL);
336
sch = gtk_clist_get_row_data(clist, row);
341
search_gui_set_current_search((search_t *)sch);
348
void on_search_selected(GtkItem * i, gpointer data)
350
search_selected = (search_t *) data;
355
* on_button_search_clicked
357
* Create a search based on query entered
360
void on_button_search_clicked(GtkButton *button, gpointer user_data)
362
gchar *e = STRTRACK(gtk_editable_get_chars
363
(GTK_EDITABLE(lookup_widget(main_window, "entry_search")), 0, -1));
366
* Even though we might not be on_the_net() yet, record the search.
367
* There is a callback mechanism when a new node is connected, which
368
* will launch the search there if it has not been sent already.
369
* --patch from Mark Schreiber, 10/01/2002
374
filter_t *default_filter;
379
* It's important gui_search_history_add is called before
380
* new_search, otherwise the search entry will not be
384
gui_search_history_add(e);
387
* We have to capture the selection here already, because
388
* new_search will trigger a rebuild of the menu as a
391
default_filter = (filter_t *)option_menu_get_selected_data
392
(lookup_widget(main_window, "optionmenu_search_filter"));
394
res = search_gui_new_search(e, 0, &search);
397
* If we should set a default filter, we do that.
399
if (res && (default_filter != NULL)) {
400
rule_t *rule = filter_new_jump_rule
401
(default_filter, RULE_FLAG_ACTIVE);
404
* Since we don't want to distrub the shadows and
405
* do a "force commit" without the user having pressed
406
* the "ok" button in the dialog, we add the rule
409
search->filter->ruleset =
410
g_list_append(search->filter->ruleset, rule);
411
rule->target->refcount ++;
423
* on_entry_search_activate
425
void on_entry_search_activate(GtkEditable * editable, gpointer user_data)
428
* Delegate to: on_button_search_clicked.
432
on_button_search_clicked(NULL, user_data);
437
* on_entry_search_changed
439
* When a search string is entered, activate the search button
442
void on_entry_search_changed(GtkEditable * editable, gpointer user_data)
444
gchar *e = STRTRACK(gtk_editable_get_chars(editable, 0, -1));
446
gtk_widget_set_sensitive
447
(lookup_widget(main_window, "button_search"), *e != 0);
453
* on_button_search_clear_clicked
455
* Clear search results, de-activate clear search button
458
void on_button_search_clear_clicked(GtkButton * button, gpointer user_data)
460
gui_search_clear_results();
462
gtk_widget_set_sensitive
463
(lookup_widget(main_window, "button_search_clear"), FALSE);
468
* on_button_search_close_clicked
470
void on_button_search_close_clicked(GtkButton * button, gpointer user_data)
474
search = search_gui_get_current_search();
477
search_gui_close_search(search);
482
* on_button_search_download_clicked
484
void on_button_search_download_clicked(GtkButton * button, gpointer user_data)
486
search_gui_download_files();
491
* on_button_search_collapse_clicked
493
void on_button_search_collapse_all_clicked(GtkButton *button, gpointer user_data)
495
search_gui_collapse_all();
500
* on_button_search_expand_clicked
502
void on_button_search_expand_all_clicked(GtkButton *button, gpointer user_data)
504
search_gui_expand_all();
509
* on_clist_search_results_key_press_event
511
gboolean on_clist_search_results_key_press_event
512
(GtkWidget *widget, GdkEventKey * event, gpointer user_data)
514
g_assert(event != NULL);
516
switch(event->keyval) {
518
search_gui_download_files();
527
* on_clist_search_results_button_press_event
529
* Handles showing the popup in the event of right-clicks and downloading
532
gboolean on_clist_search_results_button_press_event
533
(GtkWidget *widget, GdkEventButton * event, gpointer user_data)
537
static guint click_time = 0;
540
search = search_gui_get_current_search();
542
switch (event->button) {
544
/* left click section */
545
if (event->type == GDK_2BUTTON_PRESS) {
546
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),
547
"button_press_event");
550
if (event->type == GDK_BUTTON_PRESS) {
551
if ((event->time - click_time) <= 250) {
553
* 2 clicks within 250 msec == doubleclick.
554
* Surpress further events
556
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget),
557
"button_press_event");
559
if (gtk_clist_get_selection_info(GTK_CLIST(widget), event->x,
560
event->y, &row, &column)) {
562
search_gui_download_files();
566
click_time = event->time;
573
/* right click section (popup menu) */
576
gboolean search_results_show_tabs;
578
gui_prop_get_boolean(
579
PROP_SEARCH_RESULTS_SHOW_TABS,
580
&search_results_show_tabs, 0, 1);
582
gm_snprintf(tmpstr, sizeof(tmpstr), (search_results_show_tabs) ?
583
"Show search list" : "Show tabs");
586
gtk_label_set(GTK_LABEL((GTK_MENU_ITEM
587
(lookup_widget(popup_search, "popup_search_toggle_tabs"))
588
->item.bin.child)), tmpstr);
589
gtk_menu_popup(GTK_MENU(popup_search), NULL, NULL, NULL, NULL,
590
event->button, event->time);
602
* on_button_search_filter_clicked
604
void on_button_search_filter_clicked(
605
GtkButton *button, gpointer user_data)
607
filter_open_dialog();
612
* on_clist_search_results_click_column
614
* Sort search according to selected column
617
void on_clist_search_results_click_column(
618
GtkCList *clist, gint column, gpointer user_data)
622
g_assert(clist != NULL);
624
search = search_gui_get_current_search();
629
/* rotate or initialize search order */
630
if (column == search->sort_col) {
631
switch (search->sort_order) {
633
search->sort_order = SORT_DESC;
636
search->sort_order = SORT_NONE;
639
search->sort_order = SORT_ASC;
642
search->sort_col = column;
643
search->sort_order = SORT_ASC;
646
search_gui_sort_column(search, column); /* Sort column, draw arrow */
651
* on_clist_search_results_select_row:
653
* This function is called when the user selects a row in the
654
* search results pane. Autoselection takes place here.
656
void on_ctree_search_results_select_row(GtkCTree *ctree,
657
GList *node, gint column, gpointer user_data)
659
gboolean search_autoselect;
660
gboolean search_autoselect_ident;
661
gboolean search_autoselect_fuzzy;
666
if (TRUE == in_autoselect)
672
sch = search_gui_get_current_search();
673
rc = (record_t *) gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(node));
675
gui_prop_get_boolean(
676
PROP_SEARCH_AUTOSELECT,
677
&search_autoselect, 0, 1);
679
gui_prop_get_boolean(
680
PROP_SEARCH_AUTOSELECT_IDENT,
681
&search_autoselect_ident, 0, 1);
683
gui_prop_get_boolean(
684
PROP_SEARCH_AUTOSELECT_FUZZY,
685
&search_autoselect_fuzzy, 0, 1);
691
* check if config setting select all is on and only autoselect if
692
* only one item is selected (no way to merge two autoselections)
694
if (search_autoselect &&
695
(GTK_CLIST(ctree)->selection != NULL) &&
696
(GTK_CLIST(ctree)->selection->next == NULL)) {
698
x = search_cb_autoselect(ctree, GTK_CTREE_NODE(node),
699
search_autoselect_ident);
702
statusbar_gui_message(15,
703
"%d auto selected %s",
704
x, (rc->sha1 != NULL) ?
705
"by urn:sha1 and filename" : "by filename");
707
statusbar_gui_message(15, "none auto selected");
712
/* The following code will select all the children of a parent, if that
713
* parent is selected. This isn't necessary because when a node is closed
714
* it's children are already selected. This would only be useful if
715
* someone opened a node and then clicked on the parent... in which case
716
* they likely wouldn't want to select all the children. Regardless,
717
* we may want this later --- Emile
721
/* If a parent node is selected, select all children */
722
if (GTK_CLIST(ctree)->selection != NULL) {
724
rc = gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(node));
725
if (NULL != rc->sha1) {
727
key = atom_sha1_get(rc->sha1);
728
parent = find_parent_with_sha1(sch->parents, key);
730
if (NULL != parent) {
732
parent_row = GTK_CTREE_ROW(parent);
734
/* A parent exists with that sha1, is it the selected node? */
735
if ((parent == GTK_CTREE_NODE(node))
736
&& (NULL != parent_row->children)) {
737
gtk_ctree_select_recursive(ctree, GTK_CTREE_NODE(node));
749
* on_clist_search_results_unselect_row
751
void on_ctree_search_results_unselect_row(
752
GtkCTree *ctree, GList *node, gint column, gpointer user_data)
759
* on_ctree_search_results_resize_column
761
void on_ctree_search_results_resize_column(
762
GtkCList * clist, gint column, gint width, gpointer user_data)
766
/* remember the width for storing it to the config file later */
767
gui_prop_set_guint32(PROP_SEARCH_RESULTS_COL_WIDTHS, &buf, column, 1);
772
* on_button_search_passive_clicked
777
void on_button_search_passive_clicked(
778
GtkButton *button, gpointer user_data)
780
filter_t *default_filter;
784
* We have to capture the selection here already, because
785
* new_search will trigger a rebuild of the menu as a
788
default_filter = (filter_t *)
789
option_menu_get_selected_data
790
(lookup_widget(main_window, "optionmenu_search_filter"));
792
search_gui_new_search("Passive", SEARCH_PASSIVE, &search);
795
* If we should set a default filter, we do that.
797
if (default_filter != NULL) {
798
rule_t *rule = filter_new_jump_rule
799
(default_filter, RULE_FLAG_ACTIVE);
802
* Since we don't want to distrub the shadows and
803
* do a "force commit" without the user having pressed
804
* the "ok" button in the dialog, we add the rule
807
search->filter->ruleset =
808
g_list_append(search->filter->ruleset, rule);
809
rule->target->refcount ++;
816
*** Search results popup
821
* search_cb_collect_ctree_data
823
* Given a GList of GtkCTreeNodes, return a new list pointing to the row data
824
* List will have to be freed later on.
826
GList *search_cb_collect_ctree_data(GtkCTree *ctree, GList *node_list)
828
GList *data_list = NULL;
831
for(; node_list != NULL; node_list = g_list_next(node_list)) {
833
if(node_list->data != NULL) {
834
rc = gtk_ctree_node_get_row_data(ctree, node_list->data);
835
data_list = g_list_append(data_list, rc);
839
data_list = g_list_first(data_list);
846
* on_popup_search_drop_name_activate
848
* For all selected results, create a filter based on name
850
void on_popup_search_drop_name_activate(GtkMenuItem *menuitem,
853
GList *node_list, *data_list = NULL;
856
search = search_gui_get_current_search();
857
g_assert(search != NULL);
859
gtk_clist_freeze(GTK_CLIST(search->ctree));
861
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
862
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
864
g_list_foreach(data_list, (GFunc) filter_add_drop_name_rule,
867
gtk_clist_thaw(GTK_CLIST(search->ctree));
868
g_list_free(data_list);
869
g_list_free(node_list);
874
* on_popup_search_drop_sha1_activate
876
* For all selected results, create a filter based on sha1
878
void on_popup_search_drop_sha1_activate(GtkMenuItem *menuitem,
881
GList *node_list, *data_list = NULL;
884
search = search_gui_get_current_search();
885
g_assert(search != NULL);
887
gtk_clist_freeze(GTK_CLIST(search->ctree));
889
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
890
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
892
g_list_foreach(data_list, (GFunc) filter_add_drop_sha1_rule,
895
gtk_clist_thaw(GTK_CLIST(search->ctree));
896
g_list_free(data_list);
897
g_list_free(node_list);
902
* on_popup_search_drop_host_activate
904
* For all selected results, create a filter based on host
906
void on_popup_search_drop_host_activate(GtkMenuItem *menuitem,
909
GList *node_list, *data_list = NULL;
912
search = search_gui_get_current_search();
913
g_assert(search != NULL);
915
gtk_clist_freeze(GTK_CLIST(search->ctree));
917
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
918
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
920
g_list_foreach(data_list, (GFunc) filter_add_drop_host_rule,
923
gtk_clist_thaw(GTK_CLIST(search->ctree));
924
g_list_free(data_list);
925
g_list_free(node_list);
930
* on_popup_search_drop_name_global_activate
932
* For all selected results, create a global filter based on name
934
void on_popup_search_drop_name_global_activate(GtkMenuItem *menuitem,
937
GList *node_list, *data_list = NULL;
940
search = search_gui_get_current_search();
941
g_assert(search != NULL);
943
gtk_clist_freeze(GTK_CLIST(search->ctree));
945
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
946
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
948
g_list_foreach(data_list, (GFunc) filter_add_drop_name_rule,
949
filter_get_global_pre());
951
gtk_clist_thaw(GTK_CLIST(search->ctree));
952
g_list_free(data_list);
953
g_list_free(node_list);
958
* on_popup_search_drop_sha1_global_activate
960
* For all selected results, create a global filter based on sha1
963
void on_popup_search_drop_sha1_global_activate(GtkMenuItem *menuitem,
966
GList *node_list, *data_list = NULL;
969
search = search_gui_get_current_search();
970
g_assert(search != NULL);
972
gtk_clist_freeze(GTK_CLIST(search->ctree));
974
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
975
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
977
g_list_foreach(data_list, (GFunc) filter_add_drop_sha1_rule,
978
filter_get_global_pre());
980
gtk_clist_thaw(GTK_CLIST(search->ctree));
981
g_list_free(data_list);
982
g_list_free(node_list);
987
* on_popup_search_drop_host_global_activate
989
* For all selected results, create a global filter based on host
992
void on_popup_search_drop_host_global_activate(GtkMenuItem *menuitem,
995
GList *node_list, *data_list = NULL;
998
search = search_gui_get_current_search();
999
g_assert(search != NULL);
1001
gtk_clist_freeze(GTK_CLIST(search->ctree));
1003
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
1004
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
1006
g_list_foreach(data_list, (GFunc) filter_add_drop_host_rule,
1007
filter_get_global_pre());
1009
gtk_clist_thaw(GTK_CLIST(search->ctree));
1010
g_list_free(data_list);
1011
g_list_free(node_list);
1016
* on_popup_search_autodownload_name_activate
1018
* Please add comment
1021
void on_popup_search_autodownload_name_activate(GtkMenuItem *menuitem,
1024
GList *node_list, *data_list = NULL;
1027
search = search_gui_get_current_search();
1028
g_assert(search != NULL);
1030
gtk_clist_freeze(GTK_CLIST(search->ctree));
1032
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
1033
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
1035
g_list_foreach(data_list, (GFunc) filter_add_download_name_rule,
1038
gtk_clist_thaw(GTK_CLIST(search->ctree));
1039
g_list_free(data_list);
1040
g_list_free(node_list);
1045
* on_popup_search_autodownload_sha1_activate
1047
* Please add comment
1050
void on_popup_search_autodownload_sha1_activate(GtkMenuItem *menuitem,
1053
GList *node_list, *data_list = NULL;
1056
search = search_gui_get_current_search();
1057
g_assert(search != NULL);
1059
gtk_clist_freeze(GTK_CLIST(search->ctree));
1061
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
1062
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
1064
g_list_foreach(data_list, (GFunc) filter_add_download_sha1_rule,
1067
gtk_clist_thaw(GTK_CLIST(search->ctree));
1068
g_list_free(data_list);
1069
g_list_free(node_list);
1074
* on_popup_search_new_from_selected_activate
1076
* Please add comment
1079
void on_popup_search_new_from_selected_activate(GtkMenuItem *menuitem,
1082
GList *node_list, *data_list = NULL;
1085
search = search_gui_get_current_search();
1086
g_assert(search != NULL);
1088
gtk_clist_freeze(GTK_CLIST(search->ctree));
1090
node_list = g_list_copy(GTK_CLIST(search->ctree)->selection);
1091
data_list = search_cb_collect_ctree_data(search->ctree, node_list);
1093
g_list_foreach(data_list, (GFunc) gui_add_targetted_search,
1096
gtk_clist_thaw(GTK_CLIST(search->ctree));
1097
g_list_free(data_list);
1098
g_list_free(node_list);
1103
* on_popup_search_edit_filter_activate
1105
void on_popup_search_edit_filter_activate(GtkMenuItem * menuitem,
1108
filter_open_dialog();
1113
* on_popup_search_duplicate_activate
1115
* Create a new search identical to the current search
1116
* Note: Doesn't duplicate filters or passive searches yet
1118
void on_popup_search_duplicate_activate(GtkMenuItem * menuitem,
1124
gnet_prop_get_guint32_val(PROP_SEARCH_REISSUE_TIMEOUT, &timeout);
1126
search = search_gui_get_current_search();
1127
/* FIXME: should also duplicate filters! */
1128
/* FIXME: should call search_duplicate which has to be written. */
1129
/* FIXME: should properly duplicate passive searches. */
1131
search_gui_new_search_full(search->query, 0,
1132
timeout, search->sort_col, search->sort_order,
1133
search->enabled ? SEARCH_ENABLED : 0, NULL);
1138
* on_popup_search_restart_activate
1140
void on_popup_search_restart_activate(GtkMenuItem *menuitem, gpointer user_data)
1144
search = search_gui_get_current_search();
1146
search_gui_restart_search(search);
1151
* on_popup_search_resume_activate
1153
void on_popup_search_resume_activate(GtkMenuItem * menuitem, gpointer user_data)
1157
search = search_gui_get_current_search();
1159
gui_search_set_enabled(search, TRUE);
1164
* on_popup_search_stop_activate
1166
* Stop current search
1168
void on_popup_search_stop_activate
1169
(GtkMenuItem *menuitem, gpointer user_data)
1173
search = search_gui_get_current_search();
1175
gui_search_set_enabled(search, FALSE);
1180
* on_popup_search_config_cols_activate
1182
* Please add comment
1185
void on_popup_search_config_cols_activate(GtkMenuItem * menuitem,
1190
search = search_gui_get_current_search();
1191
g_return_if_fail(search != NULL);
1192
g_assert(search->ctree != NULL);
1197
/* FIXME: needs to work also in Gtk2 or be replaced. */
1198
cc = gtk_column_chooser_new(GTK_WIDGET(search->ctree));
1199
gtk_menu_popup(GTK_MENU(cc), NULL, NULL, NULL, NULL, 1, 0);
1201
/* GtkColumnChooser takes care of cleaning up itself */
1207
* on_popup_search_expand_all_activate
1209
void on_popup_search_expand_all_activate(GtkMenuItem *menuitem,
1212
search_gui_expand_all();
1218
* on_popup_search_collapse_all_activate
1220
void on_popup_search_collapse_all_activate(GtkMenuItem *menuitem,
1223
search_gui_collapse_all();
1227
#endif /* USE_GTK1 */