udapted vi.po
[rhythmbox.git] / widgets / rb-query-creator-properties.c
blob5a06c23cb44e90fa4222ee615acbd2b889bc95d5
1 /*
2 * arch-tag: Implementation of RhythmDB query creation properties
4 * Copyright (C) 2003, 2004 Colin Walters <walters@gnome.org>
5 * Copyright (C) 2005 James Livingston <walters@gnome.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <libgnome/gnome-i18n.h>
24 #include <gtk/gtk.h>
25 #include <libgnomevfs/gnome-vfs-utils.h>
27 #include "rhythmdb.h"
28 #include "rb-query-creator-private.h"
29 #include "rb-rating.h"
31 const RBQueryCreatorPropertyType string_property_type;
32 const RBQueryCreatorPropertyType escaped_string_property_type;
33 const RBQueryCreatorPropertyType rating_property_type;
34 const RBQueryCreatorPropertyType integer_property_type;
35 const RBQueryCreatorPropertyType year_property_type;
36 const RBQueryCreatorPropertyType duration_property_type;
37 const RBQueryCreatorPropertyType relative_time_property_type;
39 static GtkWidget * stringCriteriaCreateWidget (gboolean *constrain);
40 static void stringCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
41 static void stringCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
42 static void escapedStringCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
43 static void escapedStringCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
44 static GtkWidget * ratingCriteriaCreateWidget (gboolean *constrain);
45 static void ratingCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
46 static void ratingCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
47 static GtkWidget * integerCriteriaCreateWidget (gboolean *constrain);
48 static void integerCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
49 static void integerCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
50 static GtkWidget * yearCriteriaCreateWidget (gboolean *constrain);
51 static void yearCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
52 static void yearCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
53 static GtkWidget * durationCriteriaCreateWidget (gboolean *constrain);
54 static void durationCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
55 static void durationCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
56 static GtkWidget * relativeTimeCriteriaCreateWidget (gboolean *constrain);
57 static void relativeTimeCriteriaSetWidgetData (GtkWidget *widget, GValue *val);
58 static void relativeTimeCriteriaGetWidgetData (GtkWidget *widget, GValue *val);
61 * This table is the list of properties that are displayed in the query-creator
63 const RBQueryCreatorPropertyOption property_options[] =
65 { N_("Title"), RHYTHMDB_PROP_TITLE, RHYTHMDB_PROP_TITLE_FOLDED, &string_property_type },
66 { N_("Artist"), RHYTHMDB_PROP_ARTIST, RHYTHMDB_PROP_ARTIST_FOLDED, &string_property_type },
67 { N_("Album"), RHYTHMDB_PROP_ALBUM, RHYTHMDB_PROP_ALBUM_FOLDED, &string_property_type },
68 { N_("Genre"), RHYTHMDB_PROP_GENRE, RHYTHMDB_PROP_GENRE_FOLDED, &string_property_type },
69 { N_("Year"), RHYTHMDB_PROP_DATE, RHYTHMDB_PROP_DATE, &year_property_type },
70 { N_("Rating"), RHYTHMDB_PROP_RATING, RHYTHMDB_PROP_RATING, &rating_property_type },
71 { N_("Path"), RHYTHMDB_PROP_LOCATION, RHYTHMDB_PROP_LOCATION, &escaped_string_property_type },
73 { N_("Play Count"), RHYTHMDB_PROP_PLAY_COUNT, RHYTHMDB_PROP_PLAY_COUNT, &integer_property_type },
74 { N_("Track Number"), RHYTHMDB_PROP_TRACK_NUMBER, RHYTHMDB_PROP_TRACK_NUMBER, &integer_property_type },
75 { N_("Disc Number"), RHYTHMDB_PROP_DISC_NUMBER, RHYTHMDB_PROP_DISC_NUMBER, &integer_property_type },
76 { N_("Bitrate"), RHYTHMDB_PROP_BITRATE, RHYTHMDB_PROP_BITRATE, &integer_property_type },
78 { N_("Duration"), RHYTHMDB_PROP_DURATION, RHYTHMDB_PROP_DURATION, &duration_property_type },
80 { N_("Time of Last Play"), RHYTHMDB_PROP_LAST_PLAYED, RHYTHMDB_PROP_LAST_PLAYED, &relative_time_property_type },
81 { N_("Time Added to Library"), RHYTHMDB_PROP_FIRST_SEEN, RHYTHMDB_PROP_FIRST_SEEN, &relative_time_property_type },
84 const int num_property_options = G_N_ELEMENTS (property_options);
87 * This table describes which properties can be used for sorting a playlist
88 * All entries MUST have column keys column keys listed in rb-entry-view.c
90 const RBQueryCreatorSortOption sort_options[] =
92 { N_("Artist"), "Artist", N_("_In reverse alphabetical order") },
93 { N_("Album"), "Album", N_("_In reverse alphabetical order") },
94 { N_("Genre"), "Genre", N_("_In reverse alphabetical order") },
95 { N_("Title"), "Title", N_("_In reverse alphabetical order") },
96 { N_("Rating"), "Rating", N_("W_ith more highly rated tracks first") },
97 { N_("Play Count"), "PlayCount", N_("W_ith more often played songs first") },
98 { N_("Year"), "Year", N_("W_ith newer tracks first") },
99 { N_("Duration"), "Time", N_("W_ith longer tracks first") },
100 { N_("Track Number"), "Track", N_("_In decreasing order")},
101 { N_("Last Played"), "LastPlayed", N_("W_ith more recently played tracks first") },
102 { N_("Date Added"), "FirstSeen", N_("W_ith more recently added tracks first") },
105 const int num_sort_options = G_N_ELEMENTS (sort_options);
106 const int DEFAULT_SORTING_COLUMN = 0;
107 const gint DEFAULT_SORTING_ORDER = GTK_SORT_ASCENDING;
110 * This is the property type for string properties
113 const RBQueryCreatorCriteriaOption string_criteria_options[] =
115 { N_("contains"), 0, RHYTHMDB_QUERY_PROP_LIKE },
116 { N_("does not contain"), 0, RHYTHMDB_QUERY_PROP_NOT_LIKE },
117 { N_("equals"), 1, RHYTHMDB_QUERY_PROP_EQUALS },
118 { N_("starts with"), 0, RHYTHMDB_QUERY_PROP_PREFIX },
119 { N_("ends with"), 0, RHYTHMDB_QUERY_PROP_SUFFIX },
122 const RBQueryCreatorPropertyType string_property_type =
124 G_N_ELEMENTS (string_criteria_options),
125 string_criteria_options,
126 stringCriteriaCreateWidget,
127 stringCriteriaSetWidgetData,
128 stringCriteriaGetWidgetData
131 const RBQueryCreatorPropertyType escaped_string_property_type =
133 G_N_ELEMENTS (string_criteria_options),
134 string_criteria_options,
135 stringCriteriaCreateWidget,
136 escapedStringCriteriaSetWidgetData,
137 escapedStringCriteriaGetWidgetData
141 * This are the property types for numeric quantities, such as rating and playcounts
144 const RBQueryCreatorCriteriaOption numeric_criteria_options[] =
146 { N_("equals"), 1, RHYTHMDB_QUERY_PROP_EQUALS },
147 { N_("at least"), 1, RHYTHMDB_QUERY_PROP_GREATER }, /* matches if A >= B */
148 { N_("at most"), 1, RHYTHMDB_QUERY_PROP_LESS } /* matches if A <= B */
152 * Property type for date quantities
155 const RBQueryCreatorCriteriaOption year_criteria_options[] =
157 { N_("in"), 1, RHYTHMDB_QUERY_PROP_YEAR_EQUALS },
158 /* matches if within 1-JAN-YEAR to 31-DEC-YEAR */
159 { N_("after"), 1, RHYTHMDB_QUERY_PROP_YEAR_GREATER },
160 /* matches if >= 31-DEC-YEAR */
161 { N_("before"), 1, RHYTHMDB_QUERY_PROP_YEAR_LESS }
162 /* matches if < 1-DEC-YEAR */
165 const RBQueryCreatorPropertyType rating_property_type =
167 G_N_ELEMENTS (numeric_criteria_options),
168 numeric_criteria_options,
169 ratingCriteriaCreateWidget,
170 ratingCriteriaSetWidgetData,
171 ratingCriteriaGetWidgetData
174 const RBQueryCreatorPropertyType integer_property_type =
176 G_N_ELEMENTS (numeric_criteria_options),
177 numeric_criteria_options,
178 integerCriteriaCreateWidget,
179 integerCriteriaSetWidgetData,
180 integerCriteriaGetWidgetData
183 const RBQueryCreatorPropertyType year_property_type =
185 G_N_ELEMENTS (year_criteria_options),
186 year_criteria_options,
187 yearCriteriaCreateWidget,
188 yearCriteriaSetWidgetData,
189 yearCriteriaGetWidgetData
192 const RBQueryCreatorPropertyType duration_property_type =
194 G_N_ELEMENTS (numeric_criteria_options),
195 numeric_criteria_options,
196 durationCriteriaCreateWidget,
197 durationCriteriaSetWidgetData,
198 durationCriteriaGetWidgetData
202 * This is the property type for relative time properties, such as last played and first seen
205 typedef struct
207 const char *name;
208 gulong timeMultiplier;
209 } RBQueryCreatorTimeUnitOption;
211 const RBQueryCreatorCriteriaOption relative_time_criteria_options[] =
214 * Translators: this will match when within <value> of the current time
215 * e.g. "in the last" "7 days" will match if within 7 days of the current time
217 { N_("in the last"), 1, RHYTHMDB_QUERY_PROP_CURRENT_TIME_WITHIN },
220 * Translators: this is the opposite of the above, and will match if not
221 * within <value> of the current time
223 { N_("not in the last"), 1, RHYTHMDB_QUERY_PROP_CURRENT_TIME_NOT_WITHIN }
226 const RBQueryCreatorPropertyType relative_time_property_type =
228 G_N_ELEMENTS (relative_time_criteria_options),
229 relative_time_criteria_options,
230 relativeTimeCriteriaCreateWidget,
231 relativeTimeCriteriaSetWidgetData,
232 relativeTimeCriteriaGetWidgetData
235 const RBQueryCreatorTimeUnitOption time_unit_options[] =
237 { N_("seconds"), 1 },
238 { N_("minutes"), 60 },
239 { N_("hours"), 60 * 60 },
240 { N_("days"), 60 * 60 * 24 },
241 { N_("weeks"), 60 * 60 * 24 * 7 }
244 const int time_unit_options_default = 4; /* days */
247 * Implementation for the string properties, using a single GtkEntry.
250 static GtkWidget *
251 stringCriteriaCreateWidget (gboolean *constrain)
253 return gtk_entry_new ();
256 static void
257 stringCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
259 gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (val));
262 static void
263 stringCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
265 const char* text = gtk_entry_get_text (GTK_ENTRY (widget));
267 g_value_init (val, G_TYPE_STRING);
268 g_value_set_string (val, text);
271 /* escaped string operations, for use with URIs, etc */
273 static void
274 escapedStringCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
276 char *text = gnome_vfs_unescape_string (g_value_get_string (val), NULL);
277 gtk_entry_set_text (GTK_ENTRY (widget), text);
278 g_free (text);
281 static void
282 escapedStringCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
284 char *text = gnome_vfs_escape_host_and_path_string (gtk_entry_get_text (GTK_ENTRY (widget)));
286 g_value_init (val, G_TYPE_STRING);
287 g_value_set_string (val, text);
291 * Implementation for the ratings property, using the RbRating widget
294 static void
295 set_rating_score (RBRating *rating, gdouble score)
297 g_object_set (G_OBJECT (rating), "rating", score, NULL);
300 static GtkWidget *
301 ratingCriteriaCreateWidget (gboolean *constrain)
303 RBRating *rating = rb_rating_new ();
304 g_signal_connect_object (G_OBJECT (rating), "rated",
305 G_CALLBACK (set_rating_score), NULL, 0);
306 *constrain = FALSE;
307 return GTK_WIDGET (rating);
310 static void
311 ratingCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
313 g_object_set (G_OBJECT (widget), "rating", g_value_get_double (val), NULL);
316 static void
317 ratingCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
319 double rating;
320 g_object_get (G_OBJECT (widget), "rating", &rating, NULL);
322 g_value_init (val, G_TYPE_DOUBLE);
323 g_value_set_double (val, rating);
327 * Implementation for the integer properties, using a single GtkSpinButton.
330 static GtkWidget *
331 integerCriteriaCreateWidget (gboolean *constrain)
333 return gtk_spin_button_new_with_range (0.0, (double)G_MAXINT, 1.0);
336 static void
337 integerCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
339 gulong num = g_value_get_ulong (val);
340 g_assert (num <= G_MAXINT);
342 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gint)num );
345 static void
346 integerCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
348 gint num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
349 g_assert (num >= 0);
351 g_value_init (val, G_TYPE_ULONG);
352 g_value_set_ulong (val, (gulong)num);
355 /* Implementation for Year properties, using a single GtkSpinButton. */
357 static GtkWidget *
358 yearCriteriaCreateWidget (gboolean *constrain)
360 return gtk_spin_button_new_with_range (0.0, (double)G_MAXINT, 1.0);
363 static void
364 yearCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
366 GDate *date = NULL;
367 gulong num = g_value_get_ulong (val);
368 gint display_year;
369 g_assert (num <= G_MAXINT);
371 if (num != 0) {
372 /* Create a date structure to get year from */
373 date = g_date_new();
374 g_date_set_julian (date, num);
375 display_year = (gint)g_date_get_year(date);
376 g_date_free(date);
377 } else {
378 display_year = 0;
380 gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), display_year);
383 static void
384 yearCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
386 GDate *date = NULL;
387 gint num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
388 guint32 display_date;
389 g_assert (num >= 0);
391 g_value_init (val, G_TYPE_ULONG);
393 if (num != 0) {
394 /* New date structure, use year set in widget */
395 date = g_date_new_dmy (1, G_DATE_JANUARY, num);
396 display_date = g_date_get_julian (date);
397 g_date_free(date);
398 } else {
399 display_date = 0;
401 g_value_set_ulong (val, (gulong)display_date);
405 * Implementation for the duration property, using two single GtkSpinButtons.
408 static GtkWidget *
409 durationCriteriaCreateWidget (gboolean *constrain)
411 GtkBox *box;
412 GtkWidget *minutesSpin;
413 GtkWidget *minutesLabel;
414 GtkWidget *secondsSpin;
416 /* the widget for Duration is set out like the following [ 2] : [30] */
417 box = GTK_BOX (gtk_hbox_new (FALSE, 3));
419 minutesSpin = gtk_spin_button_new_with_range (0.0, G_MAXINT, 1.0);
420 gtk_box_pack_start (box, minutesSpin, FALSE, FALSE, 0);
422 minutesLabel = gtk_label_new (":");
423 gtk_box_pack_start (box, minutesLabel, FALSE, FALSE, 0);
425 secondsSpin = gtk_spin_button_new_with_range (0.0, 59.0, 1.0);
426 gtk_box_pack_start (box, secondsSpin, FALSE, FALSE, 0);
428 gtk_widget_show_all (GTK_WIDGET (box));
429 return GTK_WIDGET (box);
432 static void
433 durationCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
435 GtkSpinButton *minutesSpinner = GTK_SPIN_BUTTON (get_box_widget_at_pos (GTK_BOX (widget), 0));
436 GtkSpinButton *secondsSpinner = GTK_SPIN_BUTTON (get_box_widget_at_pos (GTK_BOX (widget), 2));
438 gtk_spin_button_set_value (minutesSpinner, (gdouble) (g_value_get_ulong (val) / 60));
439 gtk_spin_button_set_value (secondsSpinner, (gdouble) (g_value_get_ulong (val) % 60));
442 static void
443 durationCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
446 GtkSpinButton *minutesSpinner = GTK_SPIN_BUTTON (get_box_widget_at_pos (GTK_BOX (widget), 0));
447 GtkSpinButton *secondsSpinner = GTK_SPIN_BUTTON (get_box_widget_at_pos (GTK_BOX (widget), 2));
449 gint value = gtk_spin_button_get_value_as_int (minutesSpinner) * 60
450 + gtk_spin_button_get_value_as_int (secondsSpinner);
451 g_assert (value >= 0);
453 g_value_init (val, G_TYPE_ULONG);
454 g_value_set_ulong (val, (gulong) value);
458 * Implementation for the relative time properties, using a spin button and a menu.
461 static GtkWidget*
462 create_time_unit_option_menu (const RBQueryCreatorTimeUnitOption *options,
463 int length)
465 GtkWidget *menu = gtk_menu_new ();
466 GtkWidget *option_menu = gtk_option_menu_new ();
467 int i;
469 for (i = 0; i < length; i++) {
470 GtkWidget *menu_item = gtk_menu_item_new_with_label (_(options[i].name));
471 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
474 gtk_widget_show_all (menu);
475 gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
477 return option_menu;
480 static GtkWidget *
481 relativeTimeCriteriaCreateWidget (gboolean *constrain)
483 GtkBox *box;
485 GtkWidget *timeSpin;
486 GtkWidget *timeOption;
488 box = GTK_BOX (gtk_hbox_new (FALSE, 6));
490 timeSpin = gtk_spin_button_new_with_range (1.0, G_MAXINT, 1.0);
491 gtk_box_pack_start_defaults (box, timeSpin);
493 timeOption = create_time_unit_option_menu (time_unit_options, G_N_ELEMENTS (time_unit_options));
494 gtk_option_menu_set_history(GTK_OPTION_MENU (timeOption), time_unit_options_default);
495 gtk_box_pack_start_defaults (box, timeOption);
497 gtk_widget_show_all (GTK_WIDGET (box));
498 return GTK_WIDGET (box);
501 static void
502 relativeTimeCriteriaSetWidgetData (GtkWidget *widget, GValue *val)
504 GtkBox *box = GTK_BOX (widget);
506 GtkSpinButton *timeSpin = GTK_SPIN_BUTTON (get_box_widget_at_pos (box, 0));
507 GtkOptionMenu *unitMenu = GTK_OPTION_MENU (get_box_widget_at_pos (box, 1));
509 gulong time = g_value_get_ulong (val);
510 gulong unit = 0;
511 int i;
513 /* determine the best units to use for the given value */
514 for (i = 0; i < G_N_ELEMENTS(time_unit_options); i++) {
515 /* find out if the time is an even multiple of the unit */
516 if (time % time_unit_options[i].timeMultiplier == 0)
517 unit = i;
520 time = time / time_unit_options[unit].timeMultiplier;
521 g_assert (time < G_MAXINT);
522 /* set the time value and unit*/
523 gtk_option_menu_set_history(unitMenu, unit);
524 gtk_spin_button_set_value(timeSpin, time);
527 static void
528 relativeTimeCriteriaGetWidgetData (GtkWidget *widget, GValue *val)
530 GtkSpinButton *timeSpin = GTK_SPIN_BUTTON (get_box_widget_at_pos (GTK_BOX (widget), 0));
531 GtkOptionMenu *unitMenu = GTK_OPTION_MENU (get_box_widget_at_pos (GTK_BOX (widget), 1));
533 gulong timeMultiplier = time_unit_options [gtk_option_menu_get_history (unitMenu)].timeMultiplier;
534 gint value = gtk_spin_button_get_value_as_int (timeSpin) * timeMultiplier;
535 g_assert (value >= 0);
537 g_value_init (val, G_TYPE_ULONG);
538 g_value_set_ulong (val, (gulong) value);