2 * This file is part of DisOrder
3 * Copyright (C) 2008 Richard Kettlewell
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 #include "disobedience.h"
23 static GtkWidget
*choose_search_entry
;
24 static GtkWidget
*choose_next
;
25 static GtkWidget
*choose_prev
;
26 static GtkWidget
*choose_clear
;
28 /** @brief True if a search command is in flight */
29 static int choose_searching
;
31 /** @brief True if in-flight search is now known to be obsolete */
32 static int choose_search_obsolete
;
34 /** @brief Hash of all search result */
35 static hash
*choose_search_hash
;
37 static void choose_search_entry_changed(GtkEditable
*editable
,
40 int choose_is_search_result(const char *track
) {
41 return choose_search_hash
&& hash_find(choose_search_hash
, track
);
44 /** @brief Called when the cancel search button is clicked */
45 static void choose_clear_clicked(GtkButton
attribute((unused
)) *button
,
46 gpointer
attribute((unused
)) userdata
) {
47 gtk_entry_set_text(GTK_ENTRY(choose_search_entry
), "");
48 /* The changed signal will do the rest of the work for us */
51 /** @brief Called with search results */
52 static void choose_search_completed(void attribute((unused
)) *v
,
54 int nvec
, char **vec
) {
56 popup_protocol_error(0, error
);
60 /* If the search was obsoleted initiate another one */
61 if(choose_search_obsolete
) {
62 choose_search_entry_changed(0, 0);
65 //fprintf(stderr, "%d search results\n", nvec);
66 choose_search_hash
= hash_new(1);
67 for(int n
= 0; n
< nvec
; ++n
)
68 hash_add(choose_search_hash
, vec
[n
], "", HASH_INSERT
);
69 /* TODO arrange visibility of all search results */
70 event_raise("search-results-changed", 0);
73 /** @brief Called when the search entry changes */
74 static void choose_search_entry_changed
75 (GtkEditable
attribute((unused
)) *editable
,
76 gpointer
attribute((unused
)) user_data
) {
77 /* If a search is in flight don't initiate a new one until it comes back */
78 if(choose_searching
) {
79 choose_search_obsolete
= 1;
82 char *terms
= xstrdup(gtk_entry_get_text(GTK_ENTRY(choose_search_entry
)));
83 /* Strip leading and trailing space */
84 while(*terms
== ' ') ++terms
;
85 char *e
= terms
+ strlen(terms
);
86 while(e
> terms
&& e
[-1] == ' ') --e
;
89 /* Nothing to search for. Fake a completion call. */
90 choose_search_completed(0, 0, 0, 0);
93 if(disorder_eclient_search(client
, choose_search_completed
, terms
, 0)) {
94 /* Bad search terms. Fake a completion call. */
95 choose_search_completed(0, 0, 0, 0);
101 static void choose_next_clicked(GtkButton
attribute((unused
)) *button
,
102 gpointer
attribute((unused
)) userdata
) {
103 fprintf(stderr
, "next\n"); /* TODO */
106 static void choose_prev_clicked(GtkButton
attribute((unused
)) *button
,
107 gpointer
attribute((unused
)) userdata
) {
108 fprintf(stderr
, "prev\n"); /* TODO */
111 /** @brief Create the search widget */
112 GtkWidget
*choose_search_widget(void) {
114 /* Text entry box for search terms */
115 choose_search_entry
= gtk_entry_new();
116 gtk_widget_set_style(choose_search_entry
, tool_style
);
117 g_signal_connect(choose_search_entry
, "changed",
118 G_CALLBACK(choose_search_entry_changed
), 0);
119 gtk_tooltips_set_tip(tips
, choose_search_entry
,
120 "Enter search terms here; search is automatic", "");
122 /* Cancel button to clear the search */
123 choose_clear
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
);
124 gtk_widget_set_style(choose_clear
, tool_style
);
125 g_signal_connect(G_OBJECT(choose_clear
), "clicked",
126 G_CALLBACK(choose_clear_clicked
), 0);
127 gtk_tooltips_set_tip(tips
, choose_clear
, "Clear search terms", "");
129 /* Up and down buttons to find previous/next results; initially they are not
130 * usable as there are no search results. */
131 choose_prev
= iconbutton("up.png", "Previous search result");
132 g_signal_connect(G_OBJECT(choose_prev
), "clicked",
133 G_CALLBACK(choose_prev_clicked
), 0);
134 gtk_widget_set_style(choose_prev
, tool_style
);
135 gtk_widget_set_sensitive(choose_prev
, 0);
136 choose_next
= iconbutton("down.png", "Next search result");
137 g_signal_connect(G_OBJECT(choose_next
), "clicked",
138 G_CALLBACK(choose_next_clicked
), 0);
139 gtk_widget_set_style(choose_next
, tool_style
);
140 gtk_widget_set_sensitive(choose_next
, 0);
142 /* Pack the search tools button together on a line */
143 GtkWidget
*hbox
= gtk_hbox_new(FALSE
/*homogeneous*/, 1/*spacing*/);
144 gtk_box_pack_start(GTK_BOX(hbox
), choose_search_entry
,
145 TRUE
/*expand*/, TRUE
/*fill*/, 0/*padding*/);
146 gtk_box_pack_start(GTK_BOX(hbox
), choose_prev
,
147 FALSE
/*expand*/, FALSE
/*fill*/, 0/*padding*/);
148 gtk_box_pack_start(GTK_BOX(hbox
), choose_next
,
149 FALSE
/*expand*/, FALSE
/*fill*/, 0/*padding*/);
150 gtk_box_pack_start(GTK_BOX(hbox
), choose_clear
,
151 FALSE
/*expand*/, FALSE
/*fill*/, 0/*padding*/);