예제 #1
0
void
rb_podcast_main_source_add_subsources (RBPodcastMainSource *source)
{
	RhythmDBQuery *query;
	RBSource *podcast_subsource;
	RBPodcastManager *podcast_mgr;
	RhythmDB *db;
	RBShell *shell;

	g_object_get (source,
		      "shell", &shell,
		      "podcast-manager", &podcast_mgr,
		      NULL);
	g_object_get (shell, "db", &db, NULL);

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
				      RHYTHMDB_QUERY_PROP_CURRENT_TIME_WITHIN,
				      RHYTHMDB_PROP_FIRST_SEEN,
				      3600 * 24 * 7,
				      RHYTHMDB_QUERY_END);

	podcast_subsource = rb_podcast_source_new (shell,
						   podcast_mgr,
						   query,
						   _("New Episodes"),
						   RB_STOCK_AUTO_PLAYLIST);
	rhythmdb_query_free (query);
	rb_source_set_hidden_when_empty (podcast_subsource, TRUE);
	rb_shell_append_source (shell, podcast_subsource, RB_SOURCE (source));

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
				      RHYTHMDB_QUERY_PROP_CURRENT_TIME_WITHIN,
				      RHYTHMDB_PROP_LAST_SEEN,
				      3600 * 24 * 7,
				      RHYTHMDB_QUERY_END);

	podcast_subsource = rb_podcast_source_new (shell,
						   podcast_mgr,
						   query,
						   _("New Downloads"),		/* better name? */
						   RB_STOCK_AUTO_PLAYLIST);
	rhythmdb_query_free (query);
	rb_source_set_hidden_when_empty (podcast_subsource, TRUE);
	rb_shell_append_source (shell, podcast_subsource, RB_SOURCE (source));

	g_object_unref (db);
	g_object_unref (shell);
}
예제 #2
0
RBSource *
rb_podcast_main_source_new (RBShell *shell, RBPodcastManager *podcast_manager)
{
	RBSource *source;
	RhythmDBQuery *base_query;
	RhythmDB *db;

	g_object_get (shell, "db", &db, NULL);
	base_query = rhythmdb_query_parse (db,
					   RHYTHMDB_QUERY_PROP_EQUALS,
					   RHYTHMDB_PROP_TYPE,
					   RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
					   RHYTHMDB_QUERY_END);
	g_object_unref (db);

	source = RB_SOURCE (g_object_new (RB_TYPE_PODCAST_MAIN_SOURCE,
					  "name", _("Podcasts"),
					  "shell", shell,
					  "entry-type", RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
					  "source-group", RB_SOURCE_GROUP_LIBRARY,
					  "search-type", RB_SOURCE_SEARCH_INCREMENTAL,
					  "podcast-manager", podcast_manager,
					  "base-query", base_query,
					  NULL));

	rhythmdb_query_free (base_query);

	rb_shell_register_entry_type_for_source (shell, source,
						 RHYTHMDB_ENTRY_TYPE_PODCAST_FEED);
	rb_shell_register_entry_type_for_source (shell, source,
						 RHYTHMDB_ENTRY_TYPE_PODCAST_POST);

	return source;
}
예제 #3
0
/**
 * rb_query_creator_get_query:
 * @creator: #RBQueryCreator instance
 *
 * Constructs a database query that represents the criteria in the query creator.
 *
 * Return value: (transfer full): database query array
 */
GPtrArray *
rb_query_creator_get_query (RBQueryCreator *creator)
{
	RBQueryCreatorPrivate *priv;
	GPtrArray *query;
	GPtrArray *sub_query;
	GList *rows, *row;
	gboolean disjunction;

	g_return_val_if_fail (RB_IS_QUERY_CREATOR (creator), NULL);

	priv = QUERY_CREATOR_GET_PRIVATE (creator);

	disjunction = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->disjunction_check));
	sub_query = g_ptr_array_new ();
	rows = priv->rows;

	for (row = rows; row; row = row->next) {
		GtkComboBox *propmenu = GTK_COMBO_BOX (get_box_widget_at_pos (GTK_BOX (row->data),
										  0));
		GtkComboBox *criteria_menu = GTK_COMBO_BOX (get_box_widget_at_pos (GTK_BOX (row->data),
										       1));
		guint prop_position = gtk_combo_box_get_active (propmenu);
		const RBQueryCreatorPropertyOption *prop_option = &property_options[prop_position];
		const RBQueryCreatorCriteriaOption *criteria_options = prop_option->property_type->criteria_options;
		const RBQueryCreatorCriteriaOption *criteria_option = &criteria_options[gtk_combo_box_get_active (criteria_menu)];

		g_assert (prop_option->property_type->criteria_get_widget_data != NULL);
		{
			RhythmDBQueryData *data = g_new0 (RhythmDBQueryData, 1);
			GValue *val = g_new0 (GValue, 1);

			data->type = criteria_option->val;
			data->propid = criteria_option->strict ? prop_option->strict_val : prop_option->fuzzy_val;

			prop_option->property_type->criteria_get_widget_data (get_box_widget_at_pos (GTK_BOX (row->data), 2), val);
			data->val = val;

			g_ptr_array_add (sub_query, data);
			}

			if (disjunction && row->next)
				rhythmdb_query_append (priv->db,
						       sub_query,
						       RHYTHMDB_QUERY_DISJUNCTION,
						       RHYTHMDB_QUERY_END);
		}
	query = rhythmdb_query_parse (priv->db,
				      /* type=songs */
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      RHYTHMDB_ENTRY_TYPE_SONG,
				      /* the constructed query */
                                      RHYTHMDB_QUERY_SUBQUERY,
                                      sub_query,
                                      RHYTHMDB_QUERY_END);
	return query;
}
/**
 * _rb_source_search_create_simple_query:
 *
 * Creates a basic search query.
 *
 * @search: the #RBSourceSearch
 * @db: the #RhythmDB
 * @search_text: the search text such as RHYTHMDB_PROP_SEARCH_MATCH
 * @search_prop: the search property
 * @return: the #RhythmDBQuery for the search text and property, or NULL
 *   if no search text is specified.
 */
RhythmDBQuery *
_rb_source_search_create_simple_query (RBSourceSearch *search, RhythmDB *db, const char *search_text, RhythmDBPropType search_prop)
{
	if (search_text[0] == '\0')
		return NULL;

	return rhythmdb_query_parse (db, 
				     RHYTHMDB_QUERY_PROP_LIKE,
				     search_prop,
				     search_text,
				     RHYTHMDB_QUERY_END);
}
static RhythmDBQuery *
impl_create_query (RBSourceSearch *bsearch, RhythmDB *db, const char *search_text)
{
	return rhythmdb_query_parse (db,
				     RHYTHMDB_QUERY_PROP_LIKE,
				     RHYTHMDB_PROP_GENRE_FOLDED,
				     search_text,
				     RHYTHMDB_QUERY_DISJUNCTION,
				     RHYTHMDB_QUERY_PROP_LIKE,
				     RHYTHMDB_PROP_TITLE_FOLDED,
				     search_text,
				     RHYTHMDB_QUERY_END);
}
END_TEST

START_TEST (test_query_creator_load_sort_artist_dec)
{
	RhythmDBQuery *query;

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_END);
	query_creator_test_load_query (db,
				       query,
				       RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
				       "Artist", GTK_SORT_DESCENDING);
	rhythmdb_query_free (query);
}
END_TEST

START_TEST (test_query_creator_load_query_simple)
{
	RhythmDBQuery *query;

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TITLE, "foo",
				      RHYTHMDB_QUERY_END);
	query_creator_test_load_query (db,
				       query,
				       RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
				       "Title", GTK_SORT_ASCENDING);
	rhythmdb_query_free (query);
}
END_TEST

START_TEST (test_query_creator_load_query_disjunction)
{
	RhythmDBQuery *query;

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_PROP_YEAR_EQUALS, RHYTHMDB_PROP_DATE, 729025/*1997*/,
				      RHYTHMDB_QUERY_DISJUNCTION,
				      RHYTHMDB_QUERY_PROP_CURRENT_TIME_WITHIN, RHYTHMDB_PROP_LAST_PLAYED, 500,
				      RHYTHMDB_QUERY_END);
	query_creator_test_load_query (db,
				       query,
				       RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
				       "Title", GTK_SORT_ASCENDING);
	rhythmdb_query_free (query);
}
END_TEST

START_TEST (test_query_creator_load_query_multiple)
{
	RhythmDBQuery *query;

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_PROP_LIKE, RHYTHMDB_PROP_ARTIST_FOLDED, "bar",
				      RHYTHMDB_QUERY_PROP_PREFIX, RHYTHMDB_PROP_ARTIST_FOLDED, "bar",
				      RHYTHMDB_QUERY_PROP_LESS, RHYTHMDB_PROP_DURATION, 47,
				      RHYTHMDB_QUERY_END);
	query_creator_test_load_query (db,
				       query,
				       RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
				       "Title", GTK_SORT_ASCENDING);
	rhythmdb_query_free (query);
}
예제 #10
0
static void
visit_playlist_dirs (RBPspSource *source,
                     GFile *file)
{
    RBShell *shell;
    RhythmDB *db;
    RhythmDBEntryType *entry_type;
    char *playlist_path;
    char *playlist_name;
    RBSource *playlist;
    GPtrArray *query;

    playlist_path = g_file_get_uri (file);		/* or _get_path? */

    g_object_get (source,
                  "shell", &shell,
                  "entry-type", &entry_type,
                  NULL);
    g_object_get (shell,
                  "db", &db,
                  NULL);

    /* FIXME this isn't good enough, we only need the files directly under the playlist directory,
     * not sub-dirs */
    query = rhythmdb_query_parse (db,
                                  RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, entry_type,
                                  RHYTHMDB_QUERY_PROP_PREFIX, RHYTHMDB_PROP_LOCATION, playlist_path,
                                  RHYTHMDB_QUERY_END);
    g_free (playlist_path);
    g_object_unref (entry_type);

    playlist_name = g_file_get_basename (file);
    playlist = rb_auto_playlist_source_new (shell, playlist_name, FALSE);
    g_free (playlist_name);

    rb_auto_playlist_source_set_query (RB_AUTO_PLAYLIST_SOURCE (playlist), query,
                                       RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
                                       NULL, 0);
    rb_generic_player_source_add_playlist (RB_GENERIC_PLAYER_SOURCE (source), shell, RB_SOURCE (playlist));
    rhythmdb_query_free (query);

    g_object_unref (shell);
    g_object_unref (db);
}
예제 #11
0
END_TEST

START_TEST (test_query_creator_load_limit_gb)
{
	RhythmDBQuery *query;
	GArray *array;

	query = rhythmdb_query_parse (db,
				      RHYTHMDB_QUERY_END);
	array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 0);
	g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
	rb_value_array_append_data (array, G_TYPE_UINT64, (guint64)(14 * 1000));
	query_creator_test_load_query (db,
				       query,
				       RHYTHMDB_QUERY_MODEL_LIMIT_SIZE, array,
				       "Title", GTK_SORT_ASCENDING);
	rhythmdb_query_free (query);
	g_array_unref (array);
}
RBSource *
rb_podcast_main_source_new (RBShell *shell, RBPodcastManager *podcast_manager)
{
	RBSource *source;
	RhythmDBQuery *base_query;
	RhythmDB *db;
	GSettings *settings;

	g_object_get (shell, "db", &db, NULL);
	base_query = rhythmdb_query_parse (db,
					   RHYTHMDB_QUERY_PROP_EQUALS,
					   RHYTHMDB_PROP_TYPE,
					   RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
					   RHYTHMDB_QUERY_END);
	g_object_unref (db);

	settings = g_settings_new (PODCAST_SETTINGS_SCHEMA);

	source = RB_SOURCE (g_object_new (RB_TYPE_PODCAST_MAIN_SOURCE,
					  "name", _("Podcasts"),
					  "shell", shell,
					  "entry-type", RHYTHMDB_ENTRY_TYPE_PODCAST_POST,
					  "podcast-manager", podcast_manager,
					  "base-query", base_query,
					  "settings", g_settings_get_child (settings, "source"),
					  "toolbar-path", "/PodcastSourceToolBar",
					  "show-all-feeds", TRUE,
					  NULL));
	g_object_unref (settings);

	rhythmdb_query_free (base_query);

	rb_shell_register_entry_type_for_source (shell, source,
						 RHYTHMDB_ENTRY_TYPE_PODCAST_FEED);
	rb_shell_register_entry_type_for_source (shell, source,
						 RHYTHMDB_ENTRY_TYPE_PODCAST_POST);

	return source;
}
예제 #13
0
static void
impl_constructed (GObject *object)
{
	RBPodcastAddDialog *dialog;
	GtkBuilder *builder;
	GtkWidget *widget;
	GtkWidget *paned;
	GtkTreeViewColumn *column;
	GtkCellRenderer *renderer;
	RBEntryView *episodes;
	RBShellPlayer *shell_player;
	RhythmDBQuery *query;
	RhythmDBQueryModel *query_model;
	const char *episode_strings[3];

	RB_CHAIN_GOBJECT_METHOD (rb_podcast_add_dialog_parent_class, constructed, object);
	dialog = RB_PODCAST_ADD_DIALOG (object);

	g_object_get (dialog->priv->podcast_mgr, "db", &dialog->priv->db, NULL);

	builder = rb_builder_load ("podcast-add-dialog.ui", NULL);

	dialog->priv->info_bar_message = gtk_label_new ("");
	dialog->priv->info_bar = gtk_info_bar_new ();
	g_object_set (dialog->priv->info_bar, "spacing", 0, NULL);
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (dialog->priv->info_bar))),
			   dialog->priv->info_bar_message);
	gtk_widget_set_no_show_all (dialog->priv->info_bar, TRUE);
	gtk_box_pack_start (GTK_BOX (dialog), dialog->priv->info_bar, FALSE, FALSE, 0);
	gtk_widget_show (dialog->priv->info_bar_message);

	dialog->priv->subscribe_button = GTK_WIDGET (gtk_builder_get_object (builder, "subscribe-button"));
	g_signal_connect_object (dialog->priv->subscribe_button, "clicked", G_CALLBACK (subscribe_clicked_cb), dialog, 0);
	gtk_widget_set_sensitive (dialog->priv->subscribe_button, FALSE);

	dialog->priv->feed_view = GTK_WIDGET (gtk_builder_get_object (builder, "feed-view"));
	g_signal_connect (dialog->priv->feed_view, "row-activated", G_CALLBACK (feed_activated_cb), dialog);
	g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->feed_view)),
			  "changed",
			  G_CALLBACK (feed_selection_changed_cb),
			  dialog);


	dialog->priv->search_entry = rb_search_entry_new (FALSE);
	gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->search_entry), 400, -1);
	g_object_set (dialog->priv->search_entry,"explicit-mode", TRUE, NULL);
	g_signal_connect (dialog->priv->search_entry, "search", G_CALLBACK (search_cb), dialog);
	g_signal_connect (dialog->priv->search_entry, "activate", G_CALLBACK (search_cb), dialog);
	gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (builder, "search-entry-box")),
			   GTK_WIDGET (dialog->priv->search_entry));

	g_signal_connect (gtk_builder_get_object (builder, "close-button"),
			  "clicked",
			  G_CALLBACK (close_clicked_cb),
			  dialog);

	dialog->priv->feed_model = gtk_list_store_new (7,
						       G_TYPE_STRING,	/* name */
						       G_TYPE_STRING,	/* author */
						       GDK_TYPE_PIXBUF, /* image */
						       G_TYPE_FILE,	/* image file */
						       G_TYPE_INT,	/* episode count */
						       G_TYPE_POINTER,	/* RBPodcastChannel */
						       G_TYPE_ULONG);	/* date */
	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->feed_view), GTK_TREE_MODEL (dialog->priv->feed_model));

	column = gtk_tree_view_column_new_with_attributes (_("Title"), gtk_cell_renderer_pixbuf_new (), "pixbuf", FEED_COLUMN_IMAGE, NULL);
	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_attributes (column, renderer, "text", FEED_COLUMN_TITLE, NULL);

	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	renderer = gtk_cell_renderer_text_new ();
	g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
	column = gtk_tree_view_column_new_with_attributes (_("Author"), renderer, "text", FEED_COLUMN_AUTHOR, NULL);
	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	renderer = gtk_cell_renderer_text_new ();
	column = gtk_tree_view_column_new_with_attributes (_("Episodes"), renderer, NULL);
	gtk_tree_view_column_set_cell_data_func (column, renderer, episode_count_column_cell_data_func, NULL, NULL);
	episode_strings[0] = "0000";
	episode_strings[1] = _("Episodes");
	episode_strings[2] = NULL;
	rb_set_tree_view_column_fixed_width (dialog->priv->feed_view, column, renderer, episode_strings, 6);
	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->feed_view), column);

	widget = GTK_WIDGET (gtk_builder_get_object (builder, "podcast-add-dialog"));
	gtk_box_pack_start (GTK_BOX (dialog), widget, TRUE, TRUE, 0);

	/* set up episode view */
	g_object_get (dialog->priv->shell, "shell-player", &shell_player, NULL);
	episodes = rb_entry_view_new (dialog->priv->db, G_OBJECT (shell_player), TRUE, FALSE);
	g_object_unref (shell_player);

	g_signal_connect (episodes, "entry-activated", G_CALLBACK (episode_entry_activated_cb), dialog);

	/* date column */
	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new();

	gtk_tree_view_column_pack_start (column, renderer, TRUE);

	gtk_tree_view_column_set_clickable (column, TRUE);
	gtk_tree_view_column_set_resizable (column, TRUE);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
	{
		const char *sample_strings[3];
		sample_strings[0] = _("Date");
		sample_strings[1] = rb_entry_view_get_time_date_column_sample ();
		sample_strings[2] = NULL;
		rb_entry_view_set_fixed_column_width (episodes, column, renderer, sample_strings);
	}

	gtk_tree_view_column_set_cell_data_func (column, renderer,
						 (GtkTreeCellDataFunc) podcast_post_date_cell_data_func,
						 dialog, NULL);

	rb_entry_view_append_column_custom (episodes, column,
					    _("Date"), "Date",
					    (GCompareDataFunc) podcast_post_date_sort_func,
					    0, NULL);
	rb_entry_view_append_column (episodes, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (episodes, RB_ENTRY_VIEW_COL_DURATION, TRUE);
	rb_entry_view_set_sorting_order (RB_ENTRY_VIEW (episodes), "Date", GTK_SORT_DESCENDING);
	g_signal_connect (episodes,
			  "notify::sort-order",
			  G_CALLBACK (episodes_sort_changed_cb),
			  dialog);

	query = rhythmdb_query_parse (dialog->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      RHYTHMDB_ENTRY_TYPE_PODCAST_SEARCH,
				      RHYTHMDB_QUERY_END);
	query_model = rhythmdb_query_model_new_empty (dialog->priv->db);
	rb_entry_view_set_model (episodes, query_model);

	rhythmdb_do_full_query_async_parsed (dialog->priv->db, RHYTHMDB_QUERY_RESULTS (query_model), query);
	rhythmdb_query_free (query);

	g_object_unref (query_model);

	paned = GTK_WIDGET (gtk_builder_get_object (builder, "paned"));
	g_signal_connect (paned, "size-allocate", G_CALLBACK (paned_size_allocate_cb), dialog);
	gtk_paned_pack2 (GTK_PANED (paned),
			 GTK_WIDGET (episodes),
			 TRUE,
			 FALSE);

	gtk_widget_show_all (GTK_WIDGET (dialog));
	g_object_unref (builder);
}
static void
rebuild_child_model (RBLibraryBrowser *widget,
		     gint property_index,
		     gboolean query_pending)
{
	RBLibraryBrowserPrivate *priv = RB_LIBRARY_BROWSER_GET_PRIVATE (widget);
	RhythmDBPropertyModel *prop_model;
	RhythmDBQueryModel *base_model, *child_model;
	RBPropertyView *view;
	RhythmDBQuery *query;
	GList *selections;

	g_assert (property_index >= 0);
	g_assert (property_index < num_browser_properties);

	/* get the query model for the previous property view */
	view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[property_index].type);
	prop_model = rb_property_view_get_model (view);
	g_object_get (prop_model, "query-model", &base_model, NULL);

	selections = g_hash_table_lookup (priv->selections, (gpointer)browser_properties[property_index].type);
	if (selections != NULL) {

		/* create a new query model based on it, filtered by
		 * the selections of the previous property view.
		 * we need the entry type query criteria to allow the
		 * backend to optimise the query.
		 */
		query = rhythmdb_query_parse (priv->db,
				              RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, priv->entry_type,
					      RHYTHMDB_QUERY_END);
		rhythmdb_query_append_prop_multiple (priv->db,
						     query,
						     browser_properties[property_index].type,
						     selections);

		child_model = rhythmdb_query_model_new_empty (priv->db);
		if (query_pending) {
			rb_debug ("rebuilding child model for browser %d; query is pending", property_index);
			g_object_set (child_model,
				      "query", query,
				      "base-model", base_model,
				      NULL);
		} else {
			rb_debug ("rebuilding child model for browser %d; running new query", property_index);
			rhythmdb_query_model_chain (child_model, base_model, FALSE);
			rhythmdb_do_full_query_parsed (priv->db,
						       RHYTHMDB_QUERY_RESULTS (child_model),
						       query);
		}
		rhythmdb_query_free (query);
	} else {
		rb_debug ("no selection for browser %d - reusing parent model", property_index);
		child_model = g_object_ref (base_model);
	}

	/* If this is the last property, use the child model as the output model
	 * for the browser.  Otherwise, use it as the input for the next property
	 * view.
	 */
	if (property_index == num_browser_properties-1) {
		if (priv->output_model != NULL) {
			g_object_unref (priv->output_model);
		}

		priv->output_model = child_model;

		g_object_notify (G_OBJECT (widget), "output-model");

	} else {
		view = g_hash_table_lookup (priv->property_views, (gpointer)browser_properties[property_index+1].type);
		ignore_selection_changes (widget, view, TRUE);

		prop_model = rb_property_view_get_model (view);
		g_object_set (prop_model, "query-model", child_model, NULL);

		g_object_unref (child_model);

		rebuild_child_model (widget, property_index + 1, query_pending);
		restore_selection (widget, property_index + 1, query_pending);
	}

	g_object_unref (base_model);
}
예제 #15
0
static void
rb_import_errors_source_constructed (GObject *object)
{
	GObject *shell_player;
	RBImportErrorsSource *source;
	RBShell *shell;
	GPtrArray *query;
	RhythmDBQueryModel *model;
	RhythmDBEntryType *entry_type;
	GtkWidget *box;
	GtkWidget *label;

	RB_CHAIN_GOBJECT_METHOD (rb_import_errors_source_parent_class, constructed, object);

	source = RB_IMPORT_ERRORS_SOURCE (object);

	g_object_get (source,
		      "shell", &shell,
		      "entry-type", &entry_type,
		      NULL);
	g_object_get (shell, "db", &source->priv->db, NULL);
	shell_player = rb_shell_get_player (shell);
	g_object_unref (shell);

	/* construct real query */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_END);

	model = rhythmdb_query_model_new (source->priv->db, query,
					  (GCompareDataFunc) rhythmdb_query_model_string_sort_func,
					  GUINT_TO_POINTER (RHYTHMDB_PROP_LOCATION), NULL, FALSE);
	rhythmdb_query_free (query);

	/* set up entry view */
	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
						NULL, FALSE, FALSE);

	rb_entry_view_set_model (source->priv->view, model);

	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ERROR, TRUE);

	g_signal_connect_object (source->priv->view, "show_popup",
				 G_CALLBACK (rb_import_errors_source_songs_show_popup_cb), source, 0);

	g_object_set (source, "query-model", model, NULL);
	g_object_unref (model);

	/* set up query model for tracking missing plugin information */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				        RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_PROP_NOT_EQUAL,
				        RHYTHMDB_PROP_COMMENT,
					"",
				      RHYTHMDB_QUERY_END);

	source->priv->missing_plugin_model = rhythmdb_query_model_new_empty (source->priv->db);
	rhythmdb_do_full_query_async_parsed (source->priv->db,
					     RHYTHMDB_QUERY_RESULTS (source->priv->missing_plugin_model),
					     query);
	rhythmdb_query_free (query);

	/* set up info bar for triggering codec installation */
	source->priv->infobar = gtk_info_bar_new_with_buttons (_("Install Plugins"), GTK_RESPONSE_OK, NULL);
	g_signal_connect_object (source->priv->infobar,
				 "response",
				 G_CALLBACK (infobar_response_cb),
				 source, 0);

	label = gtk_label_new (_("Additional GStreamer plugins are required to play some of these files."));
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (source->priv->infobar))),
			   label);

	g_object_unref (entry_type);

	box = gtk_vbox_new (FALSE, 6);
	gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (source->priv->view), TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (box), source->priv->infobar, FALSE, FALSE, 0);

	gtk_container_add (GTK_CONTAINER (source), box);
	gtk_widget_show_all (GTK_WIDGET (source));
	gtk_widget_hide (source->priv->infobar);

	/* show the info bar when there are missing plugin entries */
	g_signal_connect_object (source->priv->missing_plugin_model,
				 "row-inserted",
				 G_CALLBACK (missing_plugin_row_inserted_cb),
				 source, 0);
	g_signal_connect_object (source->priv->missing_plugin_model,
				 "row-deleted",
				 G_CALLBACK (missing_plugin_row_deleted_cb),
				 source, 0);
}
예제 #16
0
static void
query_creator_test_load_query (RhythmDB *db,
			       RhythmDBQuery *query,
			       RhythmDBQueryModelLimitType limit_type,
			       GArray *limit_value,
			       const char *sort_column,
			       gint sort_direction)
{
	GtkWidget *creator;
	RhythmDBQuery *squery;
	RhythmDBQuery *query2 = NULL;
	GArray *limit_value2 = NULL;
	const char *sort_column2 = NULL;
	RhythmDBQueryModelLimitType limit_type2;
	gint sort_direction2;
	char *str1, *str2;

	squery = rhythmdb_query_parse (db,
				       RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, RHYTHMDB_ENTRY_TYPE_SONG,
				       RHYTHMDB_QUERY_SUBQUERY, query,
				       RHYTHMDB_QUERY_END);

	creator = rb_query_creator_new_from_query (db,
						   squery,
						   limit_type, limit_value,
						   sort_column, sort_direction);
	
	str1 = rhythmdb_query_to_string (db, squery);
	fail_unless (creator != NULL,
		     "could not create query editor for %s", str1);

	/* check queries */
	query2 = rb_query_creator_get_query (RB_QUERY_CREATOR (creator));
	str2 = rhythmdb_query_to_string (db, query2);
	fail_unless (rhythmdb_query_equal (squery, query2),
		     "queries differ: %s; %s", str1, str2);
	rhythmdb_query_free (query2);
	g_free (str2);
	g_free (str1);

	/* check limits */
	rb_query_creator_get_limit (RB_QUERY_CREATOR (creator),
				    &limit_type2, &limit_value2);
	str1 = rb_gvalue_array_to_string (limit_value);
	str2 = rb_gvalue_array_to_string (limit_value2);
	fail_unless (limit_type == limit_type2,
		     "limit types differ: %d; %d", limit_type, limit_type2);
	fail_unless (rb_value_array_equal (limit_value, limit_value2),
		     "limit values differ: %s; %s", str1, str2);
	g_free (str2);
	g_free (str1);
	if (limit_value2)
		g_array_unref (limit_value2);

	/* check sorting */
	rb_query_creator_get_sort_order (RB_QUERY_CREATOR (creator),
					 &sort_column2, &sort_direction2);
	fail_unless (strcmp (sort_column2, sort_column) == 0,
		     "sort columns differ: %s; %s", sort_column, sort_column2);
	fail_unless (sort_direction2 == sort_direction,
		     "sort directions differ: %d; %d", sort_direction, sort_direction2);

	rhythmdb_query_free (squery);
	gtk_widget_destroy (creator);
}
예제 #17
0
static void
rb_missing_files_source_constructed (GObject *object)
{
	GObject *shell_player;
	RBMissingFilesSource *source;
	RBShell *shell;
	GPtrArray *query;
	RhythmDBQueryModel *model;
	RhythmDBEntryType *entry_type;

	RB_CHAIN_GOBJECT_METHOD (rb_missing_files_source_parent_class, constructed, object);
	source = RB_MISSING_FILES_SOURCE (object);

	g_object_get (source,
		      "shell", &shell,
		      "entry-type", &entry_type,
		      NULL);
	g_object_get (shell, "db", &source->priv->db, NULL);
	shell_player = rb_shell_get_player (shell);
	g_object_unref (shell);

	/* construct real query */
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_TYPE,
					entry_type,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      	RHYTHMDB_PROP_HIDDEN,
					TRUE,
				      RHYTHMDB_QUERY_END);
	g_object_unref (entry_type);

	model = rhythmdb_query_model_new (source->priv->db, query,
					  NULL, NULL, NULL, FALSE);

	rhythmdb_query_free (query);

	g_object_set (model, "show-hidden", TRUE, NULL);

	/* set up entry view */
	source->priv->view = rb_entry_view_new (source->priv->db, shell_player,
						NULL, FALSE, FALSE);

	rb_entry_view_set_model (source->priv->view, model);

	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
/*	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_GENRE, FALSE); */
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LOCATION, TRUE);
	rb_entry_view_append_column (source->priv->view, RB_ENTRY_VIEW_COL_LAST_SEEN, TRUE);

	rb_entry_view_set_columns_clickable (source->priv->view, TRUE);

	gtk_container_add (GTK_CONTAINER (source), GTK_WIDGET (source->priv->view));
	g_signal_connect_object (source->priv->view, "show_popup",
				 G_CALLBACK (rb_missing_files_source_songs_show_popup_cb), source, 0);
	g_signal_connect_object (source->priv->view, "sort-order-changed",
				 G_CALLBACK (rb_missing_files_source_songs_sort_order_changed_cb), source, 0);

	gtk_widget_show_all (GTK_WIDGET (source));

	g_object_set (source, "query-model", model, NULL);
	g_object_unref (model);
}
static void
rb_iradio_source_do_query (RBIRadioSource *source)
{
	RhythmDBQueryModel *genre_query_model = NULL;
	RhythmDBQueryModel *station_query_model = NULL;
	RhythmDBPropertyModel *genre_model;
	GPtrArray *query;
	RhythmDBEntryType *entry_type;

	/* don't update the selection while we're rebuilding the query */
	source->priv->setting_new_query = TRUE;

	/* construct and run the query for the search box.
	 * this is used as the model for the genre view.
	 */

	g_object_get (source, "entry-type", &entry_type, NULL);
	query = rhythmdb_query_parse (source->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS,
				      RHYTHMDB_PROP_TYPE,
				      entry_type,
				      RHYTHMDB_QUERY_END);
	g_object_unref (entry_type);

	if (source->priv->search_query != NULL) {
		rhythmdb_query_append (source->priv->db,
				       query,
				       RHYTHMDB_QUERY_SUBQUERY,
				       source->priv->search_query,
				       RHYTHMDB_QUERY_END);
	}

	genre_model = rb_property_view_get_model (source->priv->genres);

	genre_query_model = rhythmdb_query_model_new_empty (source->priv->db);
	g_object_set (genre_model, "query-model", genre_query_model, NULL);

	rhythmdb_do_full_query_parsed (source->priv->db,
				       RHYTHMDB_QUERY_RESULTS (genre_query_model),
				       query);

	rhythmdb_query_free (query);
	query = NULL;

	/* check the selected genre is still available, and if not, select 'all' */
	if (source->priv->selected_genre != NULL) {
		GList *sel = NULL;

		if (!rhythmdb_property_model_iter_from_string (genre_model,
							       source->priv->selected_genre,
							       NULL)) {
			g_free (source->priv->selected_genre);
			source->priv->selected_genre = NULL;
		}

		sel = g_list_prepend (sel, source->priv->selected_genre);
		rb_property_view_set_selection (source->priv->genres, sel);
		g_list_free (sel);
	}

	/* if a genre is selected, construct a new query for it, and create
	 * a new model based on the search box query model.  otherwise, just
	 * reuse the search box query model.
	 */

	if (source->priv->selected_genre != NULL) {
		rb_debug ("matching on genre \"%s\"", source->priv->selected_genre);

		station_query_model = rhythmdb_query_model_new_empty (source->priv->db);
		query = rhythmdb_query_parse (source->priv->db,
					      RHYTHMDB_QUERY_PROP_EQUALS,
					      RHYTHMDB_PROP_GENRE,
					      source->priv->selected_genre,
					      RHYTHMDB_QUERY_END);

		g_object_set (station_query_model,
			      "query", query,
			      "base-model", genre_query_model,
			      NULL);

		rhythmdb_query_free (query);
		query = NULL;
	} else {
		station_query_model = g_object_ref (genre_query_model);
	}

	rb_entry_view_set_model (source->priv->stations, station_query_model);
	g_object_set (source, "query-model", station_query_model, NULL);

	g_object_unref (genre_query_model);
	g_object_unref (station_query_model);

	source->priv->setting_new_query = FALSE;
}
예제 #19
0
static void
impl_constructed (GObject *object)
{
	RBImportDialog *dialog;
	RhythmDBQuery *query;
	GtkBuilder *builder;
	GSettings *settings;
	char **locations;

	RB_CHAIN_GOBJECT_METHOD (rb_import_dialog_parent_class, constructed, object);
	dialog = RB_IMPORT_DIALOG (object);

	g_object_get (dialog->priv->shell,
		      "db", &dialog->priv->db,
		      "shell-player", &dialog->priv->shell_player,
		      NULL);

	/* create entry types */
	dialog->priv->entry_type = g_object_new (rb_import_dialog_entry_type_get_type (),
						 "db", dialog->priv->db,
						 "name", "import-dialog",
						 NULL);
	dialog->priv->ignore_type = g_object_new (rb_import_dialog_ignore_type_get_type (),
						  "db", dialog->priv->db,
						  "name", "import-dialog-ignore",
						  NULL);
	rhythmdb_register_entry_type (dialog->priv->db, dialog->priv->entry_type);
	rhythmdb_register_entry_type (dialog->priv->db, dialog->priv->ignore_type);


	builder = rb_builder_load ("import-dialog.ui", NULL);

	dialog->priv->import_button = GTK_WIDGET (gtk_builder_get_object (builder, "import-button"));
	g_signal_connect_object (dialog->priv->import_button, "clicked", G_CALLBACK (import_clicked_cb), dialog, 0);
	gtk_widget_set_sensitive (dialog->priv->import_button, FALSE);

	dialog->priv->copy_check = GTK_WIDGET (gtk_builder_get_object (builder, "copy-check"));

	g_signal_connect (gtk_builder_get_object (builder, "close-button"),
			  "clicked",
			  G_CALLBACK (close_clicked_cb),
			  dialog);

	dialog->priv->file_chooser = GTK_WIDGET (gtk_builder_get_object (builder, "file-chooser-button"));
	
	/* select the first library location, since the default may be
	 * the user's home dir or / or something that will take forever to scan.
	 */
	settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
	locations = g_settings_get_strv (settings, "locations");
	if (locations[0] != NULL) {
		dialog->priv->current_uri = g_strdup (locations[0]);
	} else {
		dialog->priv->current_uri = g_filename_to_uri (rb_music_dir (), NULL, NULL);
	}
	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog->priv->file_chooser),
						 dialog->priv->current_uri);
	g_strfreev (locations);
	g_object_unref (settings);

	g_signal_connect_object (dialog->priv->file_chooser, "selection-changed", G_CALLBACK (current_folder_changed_cb), dialog, 0);

	/* not sure why we have to set this, it should be the default */
	gtk_widget_set_vexpand (gtk_widget_get_parent (dialog->priv->file_chooser), FALSE);

	dialog->priv->info_bar_container = GTK_WIDGET (gtk_builder_get_object (builder, "info-bar-container"));

	/* set up entry view */
	dialog->priv->entry_view = rb_entry_view_new (dialog->priv->db, G_OBJECT (dialog->priv->shell_player), TRUE, FALSE);

	g_signal_connect (dialog->priv->entry_view, "entry-activated", G_CALLBACK (entry_activated_cb), dialog);
	g_signal_connect (dialog->priv->entry_view, "selection-changed", G_CALLBACK (selection_changed_cb), dialog);

	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_GENRE, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_YEAR, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_DURATION, FALSE);
 	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_QUALITY, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_PLAY_COUNT, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_BPM, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_COMMENT, FALSE);
	rb_entry_view_append_column (dialog->priv->entry_view, RB_ENTRY_VIEW_COL_LOCATION, FALSE);

	settings = g_settings_new ("org.gnome.rhythmbox.sources");
	g_settings_bind (settings, "visible-columns", dialog->priv->entry_view, "visible-columns", G_SETTINGS_BIND_DEFAULT);
	g_object_unref (settings);

	g_signal_connect (dialog->priv->entry_view,
			  "notify::sort-order",
			  G_CALLBACK (sort_changed_cb),
			  dialog);
	rb_entry_view_set_sorting_order (dialog->priv->entry_view, "Album", GTK_SORT_ASCENDING);

	gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (builder, "entry-view-container")),
			   GTK_WIDGET (dialog->priv->entry_view));

	dialog->priv->query_model = rhythmdb_query_model_new_empty (dialog->priv->db);
	rb_entry_view_set_model (dialog->priv->entry_view, dialog->priv->query_model);
	query = rhythmdb_query_parse (dialog->priv->db,
				      RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, dialog->priv->entry_type,
				      RHYTHMDB_QUERY_END);
	rhythmdb_do_full_query_async_parsed (dialog->priv->db, RHYTHMDB_QUERY_RESULTS (dialog->priv->query_model), query);
	rhythmdb_query_free (query);

	g_signal_connect (dialog->priv->query_model, "post-entry-delete", G_CALLBACK (entry_deleted_cb), dialog);
	g_signal_connect (dialog->priv->query_model, "row-inserted", G_CALLBACK (entry_inserted_cb), dialog);

	gtk_container_add (GTK_CONTAINER (dialog), GTK_WIDGET (gtk_builder_get_object (builder, "import-dialog")));

	gtk_widget_show_all (GTK_WIDGET (dialog));
	g_object_unref (builder);
}