1 /* Time-stamp: <2007-06-25 00:53:20 jcs>
2 |
3 | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
4 | Part of the gtkpod project.
5 |
6 | URL: http://www.gtkpod.org/
7 | URL: http://gtkpod.sourceforge.net/
8 |
9 | This program is free software; you can redistribute it and/or modify
10 | it under the terms of the GNU General Public License as published by
11 | the Free Software Foundation; either version 2 of the License, or
12 | (at your option) any later version.
13 |
14 | This program is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU General Public License for more details.
18 |
19 | You should have received a copy of the GNU General Public License
20 | along with this program; if not, write to the Free Software
21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 |
23 | iTunes and iPod are trademarks of Apple
24 |
25 | This product is not supported/written/published by Apple!
26 |
27 | $Id$
28 */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <stdlib.h>
35 #include "charset.h"
36 #include "fileselection.h"
37 #include "info.h"
38 #include "misc.h"
39 #include "misc_track.h"
40 #include "prefs.h"
41 #include "sort_window.h"
42
43
44 #define DEBUG_MISC 0
45
46 /* Concats @base_dir and @rel_dir if and only if @rel_dir is not
47 * absolute (does not start with '~' or '/'). Otherwise simply return
48 * a copy of @rel_dir. Must free return value after use */
concat_dir_if_relative(G_CONST_RETURN gchar * base_dir,G_CONST_RETURN gchar * rel_dir)49 gchar *concat_dir_if_relative (G_CONST_RETURN gchar *base_dir,
50 G_CONST_RETURN gchar *rel_dir)
51 {
52 /* sanity */
53 if (!rel_dir || !*rel_dir)
54 return g_build_filename (base_dir, rel_dir, NULL);
55 /* this constellation is nonsense... */
56 if ((*rel_dir == '/') || (*rel_dir == '~'))
57 return g_strdup (rel_dir); /* rel_dir is absolute */
58 /* make absolute path */
59 return g_build_filename (base_dir, rel_dir, NULL);
60 }
61
62
63 /*------------------------------------------------------------------*\
64 * *
65 * Ask for User Input (String, SortTab Nr.) *
66 * *
67 \*------------------------------------------------------------------*/
68
69
70 /* Retrieves a string (and option) from the user using a dialog.
71 @title: title of the dialogue (may be NULL)
72 @message: text (question) to be displayed (may be NULL)
73 @dflt: default string to be returned (may be NULL)
74 @opt_msg: message for the option checkbox (or NULL)
75 @opt_state: original state of the checkbox. Will be updated
76 return value: the string entered by the user or NULL if the dialog
77 was cancelled. */
get_user_string(gchar * title,gchar * message,gchar * dflt,gchar * opt_msg,gboolean * opt_state,const gchar * accept_button)78 gchar *get_user_string (gchar *title, gchar *message, gchar *dflt,
79 gchar *opt_msg, gboolean *opt_state, const gchar *accept_button)
80 {
81 GladeXML *xml = gtkpod_xml_new (xml_file, "input_box");
82 GtkWidget *dialog = gtkpod_xml_get_widget (xml, "input_box");
83 GtkWidget *label = gtkpod_xml_get_widget (xml, "input_box_label");
84 GtkWidget *entry = gtkpod_xml_get_widget (xml, "input_box_entry");
85 GtkWidget *checkb = gtkpod_xml_get_widget (xml, "input_box_checkbox");
86 gint response;
87 gchar *result = NULL;
88 gchar *temp;
89
90 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
91 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
92 accept_button ? accept_button : GTK_STOCK_OK, GTK_RESPONSE_OK,
93 NULL);
94
95 temp = g_markup_printf_escaped ("<span weight='bold' size='larger'>%s</span>\n\n%s", title, message);
96 gtk_label_set_markup (GTK_LABEL (label), temp);
97 g_free (temp);
98
99 if (dflt)
100 {
101 gtk_entry_set_text (GTK_ENTRY (entry), dflt);
102 gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
103 }
104
105 /* Pressing enter should activate the default response (default
106 response set above */
107 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
108
109 /* create option checkbox */
110 if (opt_msg && opt_state)
111 {
112 gtk_widget_show (checkb);
113 gtk_button_set_label (GTK_BUTTON (checkb), opt_msg);
114 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkb), *opt_state);
115 }
116
117 response = gtk_dialog_run (GTK_DIALOG (dialog));
118
119 if (response == GTK_RESPONSE_OK)
120 {
121 result = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
122
123 /* get state of checkbox only if opt_msg was non NULL */
124 if (opt_msg && checkb)
125 {
126 *opt_state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkb));
127 }
128 }
129
130 gtk_widget_destroy (dialog);
131 g_object_unref (xml);
132 return result;
133 }
134
135
136
137 /* Let the user select a sort tab number */
138 /* @text: text to be displayed */
139 /* return value: -1: user selected cancel
140 0...prefs_get_sort_tab_number()-1: selected tab */
get_sort_tab_number(gchar * text)141 gint get_sort_tab_number (gchar *text)
142 {
143 static gint last_nr = 1;
144 GtkWidget *mdialog;
145 GtkDialog *dialog;
146 GtkWidget *combo;
147 gint result;
148 gint i, nr, stn;
149 GList *list=NULL, *lnk;
150 gchar buf[20], *bufp;
151
152 mdialog = gtk_message_dialog_new (
153 GTK_WINDOW (gtkpod_window),
154 GTK_DIALOG_DESTROY_WITH_PARENT,
155 GTK_MESSAGE_QUESTION,
156 GTK_BUTTONS_OK_CANCEL,
157 "%s", text);
158
159 dialog = GTK_DIALOG (mdialog);
160
161 combo = gtk_combo_new ();
162 gtk_widget_show (combo);
163 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), combo);
164
165 stn = prefs_get_int("sort_tab_num");
166 /* Create list */
167 for (i=1; i<=stn; ++i)
168 {
169 bufp = g_strdup_printf ("%d", i);
170 list = g_list_append (list, bufp);
171 }
172
173 /* set pull down items */
174 gtk_combo_set_popdown_strings (GTK_COMBO (combo), list);
175 /* set standard entry */
176 if (last_nr > stn) last_nr = 1; /* maybe the stn has become
177 smaller... */
178 snprintf (buf, 20, "%d", last_nr);
179 gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), buf);
180
181 result = gtk_dialog_run (GTK_DIALOG (mdialog));
182
183 /* free the list */
184 for (lnk = list; lnk; lnk = lnk->next)
185 {
186 C_FREE (lnk->data);
187 }
188 g_list_free (list);
189 list = NULL;
190
191 if (result == GTK_RESPONSE_CANCEL)
192 {
193 nr = -1; /* no selection */
194 }
195 else
196 {
197 bufp = gtk_editable_get_chars (GTK_EDITABLE (GTK_COMBO (combo)->entry),
198 0, -1);
199 nr = atoi (bufp)-1;
200 last_nr = nr+1;
201 C_FREE (bufp);
202 }
203
204 gtk_widget_destroy (mdialog);
205
206 return nr;
207 }
208
209
210
211
212 /*------------------------------------------------------------------*\
213 * *
214 * Functions for blocking widgets (block input) *
215 * *
216 \*------------------------------------------------------------------*/
217
218 /* --------------------------------------------------------------*/
219 /* are widgets blocked at the moment? */
220 gboolean widgets_blocked = FALSE;
221 struct blocked_widget { /* struct to be kept in blocked_widgets */
222 GtkWidget *widget; /* widget that has been turned insensitive */
223 gboolean sensitive; /* state of the widget before */
224 };
225 /* --------------------------------------------------------------*/
226
227
228 enum {
229 BR_BLOCK,
230 BR_RELEASE,
231 BR_UPDATE
232 };
233
234 /* function to add one widget to the blocked_widgets list */
add_blocked_widget(GList * blocked_widgets,gchar * name)235 static GList *add_blocked_widget (GList *blocked_widgets, gchar *name)
236 {
237 GtkWidget *w;
238 struct blocked_widget *bw;
239
240 if((w = gtkpod_xml_get_widget (main_window_xml, name)))
241 {
242 bw = g_malloc0 (sizeof (struct blocked_widget));
243 bw->widget = w;
244 /* we don't have to set the sensitive flag right now. It's
245 * done in "block_widgets ()" */
246 blocked_widgets = g_list_append (blocked_widgets, bw);
247 }
248 return blocked_widgets;
249 }
250
251 /* called by block_widgets() and release_widgets() */
252 /* "block": TRUE = block, FALSE = release */
block_release_widgets(gint action,GtkWidget * w,gboolean sens)253 static void block_release_widgets (gint action, GtkWidget *w, gboolean sens)
254 {
255 /* list with the widgets that are turned insensitive during
256 import/export...*/
257 static GList *bws = NULL;
258 static gint count = 0; /* how many times are the widgets blocked? */
259 GList *l;
260 struct blocked_widget *bw;
261
262 /* Create a list of widgets that are to be turned insensitive when
263 * importing/exporting, adding tracks or directories etc. */
264 if (bws == NULL)
265 {
266 bws = add_blocked_widget (bws, "menubar");
267 bws = add_blocked_widget (bws, "load_ipods_button");
268 bws = add_blocked_widget (bws, "save_changes_button");
269 bws = add_blocked_widget (bws, "add_files_button");
270 bws = add_blocked_widget (bws, "add_dirs_button");
271 bws = add_blocked_widget (bws, "add_PL_button");
272 bws = add_blocked_widget (bws, "new_PL_button");
273 widgets_blocked = FALSE;
274 }
275
276 switch (action)
277 {
278 case BR_BLOCK:
279 /* we must block the widgets */
280 ++count; /* increase number of locks */
281 if (!widgets_blocked)
282 { /* only block widgets, if they are not already blocked */
283 for (l = bws; l; l = l->next)
284 {
285 bw = (struct blocked_widget *)l->data;
286 /* remember the state the widget was in before */
287 bw->sensitive = GTK_WIDGET_SENSITIVE (bw->widget);
288 gtk_widget_set_sensitive (bw->widget, FALSE);
289 }
290 sort_window_block ();
291 widgets_blocked = TRUE;
292 }
293 break;
294 case BR_RELEASE:
295 /* release the widgets if --count == 0 */
296 if (widgets_blocked)
297 { /* only release widgets, if they are blocked */
298 --count;
299 if (count == 0)
300 {
301 for (l = bws; l; l = l->next)
302 {
303 bw = (struct blocked_widget *)l->data;
304 gtk_widget_set_sensitive (bw->widget, bw->sensitive);
305 }
306
307 sort_window_release ();
308 widgets_blocked = FALSE;
309 }
310 }
311 break;
312 case BR_UPDATE:
313 if (widgets_blocked)
314 { /* only update widgets, if they are blocked */
315 for (l = bws; l; l = l->next)
316 { /* find the required widget */
317 bw = (struct blocked_widget *)l->data;
318 if (bw->widget == w)
319 { /* found -> set to new desired state */
320 bw->sensitive = sens;
321 break;
322 }
323 }
324 }
325 break;
326 }
327 }
328
329
330 /* Block widgets (turn insensitive) listed in "bws" */
block_widgets(void)331 void block_widgets (void)
332 {
333 block_release_widgets (BR_BLOCK, NULL, FALSE);
334 }
335
336 /* Release widgets (i.e. return them to their state before
337 "block_widgets() was called */
release_widgets(void)338 void release_widgets (void)
339 {
340 block_release_widgets (BR_RELEASE, NULL, FALSE);
341 }
342
update_blocked_widget(GtkWidget * w,gboolean sens)343 void update_blocked_widget (GtkWidget *w, gboolean sens)
344 {
345 block_release_widgets (BR_UPDATE, w, sens);
346 }
347