⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st-category-store.c

📁 linux下网络收音机的源码
💻 C
字号:
/* * 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 <string.h>#include "sg-util.h"#include "sgtk-util.h"#include "st-category-store.h"#include "st-stock.h"#include "st-handler.h"/*** type definitions ********************************************************/enum {  CATEGORY_APPENDED,  LAST_SIGNAL};struct _STCategoryStorePrivate{  GNode		*stock_categories;};typedef struct{  STCategoryStore	*store;  gboolean		has_selection;  STCategoryBag		*main_category;} MergeInfo;typedef struct{  STCategoryStoreForeachCallback	cb;  gpointer				data;} ForeachInfo;/*** variable declarations ***************************************************/static unsigned int category_store_signals[LAST_SIGNAL] = { 0 };/*** function declarations ***************************************************/static void st_category_store_class_init (STCategoryStoreClass *class);static void st_category_store_init (STCategoryStore *store);static void st_category_store_update_icon (STCategoryStore *store,					   STCategoryBag *bag);static void st_category_store_weak_notify (gpointer data,					   GObject *former_store);static void st_category_store_category_weak_notify (gpointer data,						    GObject *former_bag);static void st_category_store_notify_task_thread_h (GObject *object,						    GParamSpec *spec,						    gpointer user_data);static gboolean st_category_store_append_node_cb (GNode *node, gpointer data);static gboolean st_category_store_merge_node_cb (GNode *node, gpointer data);static gboolean st_category_store_merge_node_foreach_cb (GtkTreeModel *model,							 GtkTreePath *path,							 GtkTreeIter *iter,							 gpointer data);static gboolean st_category_store_merge_node_stock_cb (GNode *node,						       gpointer data);static gboolean st_category_store_foreach_cb (GtkTreeModel *model,					      GtkTreePath *path,					      GtkTreeIter *iter,					      gpointer data);/*** implementation **********************************************************/GTypest_category_store_get_type (void){  static GType category_store_type = 0;    if (! category_store_type)    {      static const GTypeInfo category_store_info = {	sizeof(STCategoryStoreClass),	NULL,	NULL,	(GClassInitFunc) st_category_store_class_init,	NULL,	NULL,	sizeof(STCategoryStore),	0,	(GInstanceInitFunc) st_category_store_init,      };            category_store_type = g_type_register_static(GTK_TYPE_TREE_STORE,						   "STCategoryStore",						   &category_store_info,						   0);    }  return category_store_type;}static voidst_category_store_class_init (STCategoryStoreClass *class){  g_type_class_add_private(class, sizeof(STCategoryStorePrivate));  category_store_signals[CATEGORY_APPENDED] = g_signal_new("category-appended",							   ST_TYPE_CATEGORY_STORE,							   G_SIGNAL_RUN_LAST,							   G_STRUCT_OFFSET(STCategoryStoreClass, category_appended),							   NULL,							   NULL,							   g_cclosure_marshal_VOID__OBJECT,							   G_TYPE_NONE,							   1,							   ST_TYPE_CATEGORY_BAG);}static voidst_category_store_init (STCategoryStore *store){  store->priv = G_TYPE_INSTANCE_GET_PRIVATE(store, ST_TYPE_CATEGORY_STORE, STCategoryStorePrivate);}STCategoryStore *st_category_store_new (GNode *stock_categories){  STCategoryStore *store;  GType types[] = {    ST_TYPE_CATEGORY_BAG,    G_TYPE_STRING,    G_TYPE_STRING,    G_TYPE_STRING,    G_TYPE_STRING  };  g_return_val_if_fail(stock_categories != NULL, NULL);  store = g_object_new(ST_TYPE_CATEGORY_STORE, NULL);  gtk_tree_store_set_column_types(GTK_TREE_STORE(store),				  ST_CATEGORY_STORE_N_COLUMNS,				  types);  /* make countable (before we start appending categories) */  sgtk_tree_model_make_countable(GTK_TREE_MODEL(store));  /* we ship the store with stock categories already appended */  store->priv->stock_categories = stock_categories;  st_category_store_append_node(store, store->priv->stock_categories);  return store;}voidst_category_store_append (STCategoryStore *store,			  STCategoryBag *bag,			  STCategoryBag *parent){  GtkTreeIter iter;  g_return_if_fail(ST_IS_CATEGORY_STORE(store));  g_return_if_fail(ST_IS_CATEGORY_BAG(bag));  gtk_tree_store_append(GTK_TREE_STORE(store), &iter, parent ? &parent->iter : NULL);  bag->iter = iter;  gtk_tree_store_set(GTK_TREE_STORE(store), &iter,		     ST_CATEGORY_STORE_COLUMN_BAG, bag,		     ST_CATEGORY_STORE_COLUMN_LABEL, ST_CATEGORY(bag)->label,		     -1);  st_category_store_update_icon(store, bag);  g_signal_connect(bag, "notify::task-thread", G_CALLBACK(st_category_store_notify_task_thread_h), store);  g_object_weak_ref(G_OBJECT(store), st_category_store_weak_notify, bag);  g_object_weak_ref(G_OBJECT(bag), st_category_store_category_weak_notify, store);  g_signal_emit(store, category_store_signals[CATEGORY_APPENDED], 0, bag);}static voidst_category_store_weak_notify (gpointer data, GObject *former_store){  STCategoryBag *bag = data;  g_object_weak_unref(G_OBJECT(bag), st_category_store_category_weak_notify, former_store);  g_signal_handlers_disconnect_by_func(bag, st_category_store_notify_task_thread_h, former_store);}static voidst_category_store_category_weak_notify (gpointer data, GObject *former_bag){  STCategoryStore *store = data;  g_object_weak_unref(G_OBJECT(store), st_category_store_weak_notify, former_bag);}static voidst_category_store_update_icon (STCategoryStore *store, STCategoryBag *bag){  STThread *task_thread;  const char *stock_id_closed;  const char *stock_id_open;  g_return_if_fail(ST_IS_CATEGORY_STORE(store));  g_return_if_fail(ST_IS_CATEGORY_BAG(bag));  task_thread = st_category_bag_get_task_thread(bag);  if (ST_CATEGORY_BAG_IS(bag, ST_CATEGORY_BAG_MAIN))    stock_id_closed = task_thread ? ST_STOCK_MAIN_CATEGORY_RUNNING : ST_STOCK_MAIN_CATEGORY;  else if (ST_CATEGORY_BAG_IS(bag, ST_CATEGORY_BAG_SEARCH))    stock_id_closed = task_thread ? ST_STOCK_SEARCH_CATEGORY_RUNNING : ST_STOCK_SEARCH_CATEGORY;  else    stock_id_closed = task_thread ? ST_STOCK_CATEGORY_RUNNING : ST_STOCK_CATEGORY;  stock_id_open = task_thread ? ST_STOCK_CATEGORY_OPEN_RUNNING : ST_STOCK_CATEGORY_OPEN;  gtk_tree_store_set(GTK_TREE_STORE(store), &bag->iter,		     /* used when is-expander is false */		     ST_CATEGORY_STORE_COLUMN_STOCK_ID, stock_id_closed,		     /* used when is-expander is true */		     ST_CATEGORY_STORE_COLUMN_STOCK_ID_CLOSED, stock_id_closed,		     ST_CATEGORY_STORE_COLUMN_STOCK_ID_OPEN, stock_id_open,		     -1);}static voidst_category_store_notify_task_thread_h (GObject *object,					GParamSpec *spec,					gpointer user_data){  STCategoryBag *bag = ST_CATEGORY_BAG(object);  STCategoryStore *store = user_data;  st_category_store_update_icon(store, bag);}voidst_category_store_append_node (STCategoryStore *store, GNode *node){  g_return_if_fail(ST_IS_CATEGORY_STORE(store));  g_return_if_fail(node != NULL);  g_node_traverse(node,		  G_PRE_ORDER,		  G_TRAVERSE_ALL,		  -1,		  st_category_store_append_node_cb,		  store);}static gbooleanst_category_store_append_node_cb (GNode *node, gpointer data){  if (node->data)    {      STCategoryStore *store = data;      STCategoryBag *bag = node->data;      STCategoryBag *parent = node->parent && node->parent->data ? node->parent->data : NULL;      st_category_store_append(store, bag, parent);    }  return FALSE;			/* continue */}/* do NOT use while a reload of the same tab is in progress */voidst_category_store_merge_node (STCategoryStore *store, GNode *node){  MergeInfo info = { store, FALSE, NULL };  g_return_if_fail(ST_IS_CATEGORY_STORE(store));  g_return_if_fail(node != NULL);  g_node_traverse(node,		  G_PRE_ORDER,		  G_TRAVERSE_ALL,		  -1,		  st_category_store_merge_node_cb,		  &info);  if (! info.has_selection)    {      g_node_traverse(store->priv->stock_categories,		      G_PRE_ORDER,		      G_TRAVERSE_ALL,		      -1,		      st_category_store_merge_node_stock_cb,		      &info);      if (! info.has_selection)	st_category_bag_select(info.main_category);    }  st_category_store_clear(store);  st_category_store_append_node(store, node);}static gbooleanst_category_store_merge_node_cb (GNode *node, gpointer data){  if (node->data)    {      MergeInfo *info = data;      gtk_tree_model_foreach(GTK_TREE_MODEL(info->store),			     st_category_store_merge_node_foreach_cb,			     &node->data);      if (ST_CATEGORY_BAG_IS_SELECTED((STCategoryBag *) node->data))	info->has_selection = TRUE;    }    return FALSE;			/* continue */}static gbooleanst_category_store_merge_node_foreach_cb (GtkTreeModel *model,					 GtkTreePath *path,					 GtkTreeIter *iter,					 gpointer data){  STCategoryBag **bag = data;  STCategoryBag *this_bag;  gboolean status;  gtk_tree_model_get(model, iter, ST_CATEGORY_STORE_COLUMN_BAG, &this_bag, -1);  if (! ST_CATEGORY_BAG_IS_STOCK(this_bag)      && ST_CATEGORY_BAG_IS(this_bag, ST_CATEGORY(*bag)->name))    {      st_handler_event_category_free(this_bag->handler, this_bag->category);      this_bag->category = ST_CATEGORY(*bag);      ST_CATEGORY(*bag) = NULL;      g_object_unref(*bag);      *bag = this_bag;      return TRUE;		/* stop */    }  else    {      g_object_unref(this_bag);      return FALSE;		/* continue */    }  return status;}static gbooleanst_category_store_merge_node_stock_cb (GNode *node, gpointer data){  MergeInfo *info = data;  if (node->data)    {      STCategoryBag *bag = node->data;      if (ST_CATEGORY_BAG_IS_SELECTED(bag))	info->has_selection = TRUE;      else if (ST_CATEGORY_BAG_IS(bag, ST_CATEGORY_BAG_MAIN))	info->main_category = bag;    }  return info->has_selection;}voidst_category_store_foreach (STCategoryStore *store,			   STCategoryStoreForeachCallback cb,			   gpointer data){  ForeachInfo info = { cb, data };  g_return_if_fail(ST_IS_CATEGORY_STORE(store));    gtk_tree_model_foreach(GTK_TREE_MODEL(store),			 st_category_store_foreach_cb,			 &info);}static gbooleanst_category_store_foreach_cb (GtkTreeModel *model,			      GtkTreePath *path,			      GtkTreeIter *iter,			      gpointer data){  ForeachInfo *info = data;  STCategoryBag *bag;  GtkTreeIter parent_iter;  STCategoryBag *parent_bag = NULL;  gboolean status;  gtk_tree_model_get(model, iter, ST_CATEGORY_STORE_COLUMN_BAG, &bag, -1);  if (gtk_tree_model_iter_parent(model, &parent_iter, iter))    gtk_tree_model_get(model, &parent_iter, ST_CATEGORY_STORE_COLUMN_BAG, &parent_bag, -1);  status = info->cb(ST_CATEGORY_STORE(model), bag, parent_bag, info->data);  g_object_unref(bag);  if (parent_bag)    g_object_unref(parent_bag);  return status;}voidst_category_store_clear (STCategoryStore *store){  g_return_if_fail(ST_IS_CATEGORY_STORE(store));  gtk_tree_store_clear(GTK_TREE_STORE(store));  st_category_store_append_node(store, store->priv->stock_categories);}gbooleanst_category_store_search_equal_func (GtkTreeModel *model,				     int column,				     const char *key,				     GtkTreeIter *iter,				     gpointer search_data){  char *label;  gboolean equal = FALSE;  gtk_tree_model_get(model, iter, ST_CATEGORY_STORE_COLUMN_LABEL, &label, -1);  equal = label && sg_utf8_strcasecontains(label, key);  g_free(label);  return ! equal;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -