st-stream-store.c
来自「linux下网络收音机的源码」· C语言 代码 · 共 405 行
C
405 行
/* * Copyright (c) 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <glib/gi18n.h>#include "sg-util.h"#include "sgtk-util.h"#include "st-stream-store.h"#include "st-handler-field.h"#include "st-handler.h"/*** type definitions ********************************************************/struct _STStreamStorePrivate{ gboolean touched;};/*** variable declarations ***************************************************/static GdkPixbuf *blank_pixbuf = NULL;/*** function declarations ***************************************************/static void st_stream_store_class_init (STStreamStoreClass *class);static void st_stream_store_init (STStreamStore *store);static void st_stream_store_sort_column_changed_h (GtkTreeSortable *treesortable, gpointer user_data);static void st_stream_store_weak_notify (gpointer data, GObject *former_store);static void st_stream_store_stream_weak_notify (gpointer data, GObject *former_bag);static void st_stream_store_stream_changed_h (STStreamBag *bag, gpointer user_data);static void st_stream_store_stream_state_changed_h (STStreamBag *bag, gboolean running, gpointer user_data);static void st_stream_store_stream_deleted_h (STStreamBag *bag, gpointer user_data);static void st_stream_store_update (STStreamStore *store, STStreamBag *bag);/*** implementation **********************************************************/GTypest_stream_store_get_type (void){ static GType stream_store_type = 0; if (! stream_store_type) { static const GTypeInfo stream_store_info = { sizeof(STStreamStoreClass), NULL, NULL, (GClassInitFunc) st_stream_store_class_init, NULL, NULL, sizeof(STStreamStore), 0, (GInstanceInitFunc) st_stream_store_init }; stream_store_type = g_type_register_static(GTK_TYPE_LIST_STORE, "STStreamStore", &stream_store_info, 0); } return stream_store_type;}static voidst_stream_store_class_init (STStreamStoreClass *class){ gboolean status; int width; int height; g_type_class_add_private(class, sizeof(STStreamStorePrivate)); /* create a blank pixbuf for ST_STREAM_BAG_STATE_NORMAL */ status = gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); g_return_if_fail(status == TRUE); blank_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); gdk_pixbuf_fill(blank_pixbuf, 0); /* fill with transparent black */}static voidst_stream_store_init (STStreamStore *store){ store->priv = G_TYPE_INSTANCE_GET_PRIVATE(store, ST_TYPE_STREAM_STORE, STStreamStorePrivate);}STStreamStore *st_stream_store_new (STHandler *handler){ STStreamStore *store; GType *types; int i = ST_STREAM_STORE_N_STOCK_COLUMNS; GSList *fields; GSList *l; int sort_index; g_return_val_if_fail(ST_IS_HANDLER(handler), NULL); store = g_object_new(ST_TYPE_STREAM_STORE, NULL); fields = st_handler_get_fields(handler); /* create the store */ types = g_new(GType, ST_STREAM_STORE_N_STOCK_COLUMNS + g_slist_length(fields)); types[ST_STREAM_STORE_COLUMN_BAG] = ST_TYPE_STREAM_BAG; types[ST_STREAM_STORE_COLUMN_STOCK_ID] = G_TYPE_STRING; types[ST_STREAM_STORE_COLUMN_PIXBUF] = GDK_TYPE_PIXBUF; SG_LIST_FOREACH(l, fields) { STHandlerField *field = l->data; if (ST_HANDLER_FIELD_IS_VISIBLE(field)) { GType type = st_handler_field_get_type(field); /* keep in sync with st_stream_store_update() */ if (type == G_TYPE_BOOLEAN || type == G_TYPE_VALUE_ARRAY) type = G_TYPE_STRING; types[i++] = type; } } gtk_list_store_set_column_types(GTK_LIST_STORE(store), i, types); g_free(types); /* set the sort column, if any */ sort_index = st_handler_get_fields_sort_index(handler); if (sort_index) gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), sort_index + ST_STREAM_STORE_N_STOCK_COLUMNS - 1, /* we substract 1 because 0 means "no sort column" */ st_handler_get_fields_sort_order(handler)); /* bind signals */ g_signal_connect(store, "sort-column-changed", G_CALLBACK(st_stream_store_sort_column_changed_h), handler); sgtk_tree_model_make_countable(GTK_TREE_MODEL(store)); return store;}static voidst_stream_store_sort_column_changed_h (GtkTreeSortable *treesortable, gpointer user_data){ int sort_column_id; GtkSortType order; if (gtk_tree_sortable_get_sort_column_id(treesortable, &sort_column_id, &order)) { STHandler *handler = user_data; st_handler_set_fields_sort_index(handler, sort_column_id - ST_STREAM_STORE_N_STOCK_COLUMNS + 1); /* we add 1 because 0 means "no sort column" */ st_handler_set_fields_sort_order(handler, order); }}voidst_stream_store_append (STStreamStore *store, STStreamBag *bag){ GtkTreeIter iter; g_return_if_fail(ST_IS_STREAM_STORE(store)); g_return_if_fail(ST_IS_STREAM_BAG(bag)); gtk_list_store_append(GTK_LIST_STORE(store), &iter); bag->iter = iter; gtk_list_store_set(GTK_LIST_STORE(store), &iter, ST_STREAM_STORE_COLUMN_BAG, bag, -1); gtk_list_store_set(GTK_LIST_STORE(store), &iter, ST_STREAM_STORE_COLUMN_PIXBUF, blank_pixbuf, -1); st_stream_store_update(store, bag); g_object_connect(bag, "signal::changed", st_stream_store_stream_changed_h, store, "signal::state-changed", st_stream_store_stream_state_changed_h, store, "signal::deleted", st_stream_store_stream_deleted_h, store, NULL); g_object_weak_ref(G_OBJECT(store), st_stream_store_weak_notify, bag); g_object_weak_ref(G_OBJECT(bag), st_stream_store_stream_weak_notify, store);}static voidst_stream_store_weak_notify (gpointer data, GObject *former_store){ STStreamBag *bag = data; g_object_weak_unref(G_OBJECT(bag), st_stream_store_stream_weak_notify, former_store); g_object_disconnect(bag, "any-signal", st_stream_store_stream_changed_h, former_store, "any-signal", st_stream_store_stream_state_changed_h, former_store, "any-signal", st_stream_store_stream_deleted_h, former_store, NULL);}static voidst_stream_store_stream_weak_notify (gpointer data, GObject *former_bag){ STStreamStore *store = data; g_object_weak_unref(G_OBJECT(store), st_stream_store_weak_notify, former_bag);}static voidst_stream_store_stream_changed_h (STStreamBag *bag, gpointer user_data){ STStreamStore *store = user_data; st_stream_store_update(store, bag); st_stream_store_touch(store);}static voidst_stream_store_stream_state_changed_h (STStreamBag *bag, gboolean running, gpointer user_data){ STStreamStore *store = user_data; gtk_list_store_set(GTK_LIST_STORE(store), &bag->iter, ST_STREAM_STORE_COLUMN_STOCK_ID, running ? GTK_STOCK_EXECUTE : NULL, ST_STREAM_STORE_COLUMN_PIXBUF, running ? NULL : blank_pixbuf, -1);}static voidst_stream_store_stream_deleted_h (STStreamBag *bag, gpointer user_data){ STStreamStore *store = user_data; g_object_disconnect(bag, "any-signal", st_stream_store_stream_changed_h, store, "any-signal", st_stream_store_stream_state_changed_h, store, "any-signal", st_stream_store_stream_deleted_h, store, NULL); gtk_list_store_remove(GTK_LIST_STORE(store), &bag->iter); st_stream_store_touch(store);}voidst_stream_store_append_list (STStreamStore *store, GSList *list){ GSList *l; g_return_if_fail(ST_IS_STREAM_STORE(store)); SG_LIST_FOREACH(l, list) st_stream_store_append(store, l->data);}static voidst_stream_store_update (STStreamStore *store, STStreamBag *bag){ int i = ST_STREAM_STORE_N_STOCK_COLUMNS; GSList *l; g_return_if_fail(ST_IS_STREAM_STORE(store)); g_return_if_fail(ST_IS_STREAM_BAG(bag)); SG_LIST_FOREACH(l, st_handler_get_fields(bag->handler)) { STHandlerField *field = l->data; if (ST_HANDLER_FIELD_IS_VISIBLE(field)) { GValue value = { 0, }; st_stream_bag_get_field(bag, field, &value); if (G_VALUE_HOLDS_BOOLEAN(&value)) { gboolean b = g_value_get_boolean(&value); g_value_unset(&value); g_value_init(&value, G_TYPE_STRING); g_value_set_string(&value, b ? _("Yes") : _("No")); } else if (G_VALUE_HOLDS(&value, G_TYPE_VALUE_ARRAY)) { GValueArray *value_array; char *str; value_array = g_value_get_boxed(&value); str = value_array ? sg_value_array_get_string(value_array) : NULL; g_value_unset(&value); g_value_init(&value, G_TYPE_STRING); g_value_take_string(&value, str); } gtk_list_store_set_value(GTK_LIST_STORE(store), &bag->iter, i++, &value); g_value_unset(&value); } }}voidst_stream_store_foreach (STStreamStore *store, STStreamStoreForeachCallback cb, gpointer data){ GtkTreeIter iter; gboolean valid; g_return_if_fail(ST_IS_STREAM_STORE(store)); valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); while (valid) { STStreamBag *bag; gboolean status; gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, ST_STREAM_STORE_COLUMN_BAG, &bag, -1); status = cb(store, bag, data); g_object_unref(bag); if (status) break; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); }}gbooleanst_stream_store_search_equal_func (GtkTreeModel *model, int column, const char *key, GtkTreeIter *iter, gpointer search_data){ STStreamBag *bag; gboolean matches; gtk_tree_model_get(model, iter, ST_STREAM_STORE_COLUMN_BAG, &bag, -1); matches = st_stream_bag_matches(bag, key, FALSE); g_object_unref(bag); return ! matches;}voidst_stream_store_touch (STStreamStore *store){ g_return_if_fail(ST_IS_STREAM_STORE(store)); store->priv->touched = TRUE;}gbooleanst_stream_store_is_touched (STStreamStore *store){ g_return_val_if_fail(ST_IS_STREAM_STORE(store), FALSE); return store->priv->touched;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?