代码摘自liferea
功能要求:
现在我们想自己定义一些类型,这些类型都是 nodeTypePtr 的子类型,这些类型包括:
feed
root
folder
vfolder
node
newsbin
以上都是一些类型(就像gvolume, gfile, gchar等等类型)具体的含义我们可以暂时不用管。然后,在一个init函数中通过调用类似XXX_type_register的函数来进行注册。注册好以后可以通过nodeTypePtr node_str_to_type(gchar *str) 这样的函数来获得对应的子类型。
nodeTypePtr类型的数据结构:
node_type.h:
typedef struct nodeType { gulong capabilities; /**< bitmask of node type capabilities */ gchar *id; /**< type id (used for type attribute in OPML export) */ gpointer icon; /**< default icon */ /* For method documentation see the wrappers defined below! All methods are mandatory for each node type. */ void (*import) (nodePtr node, nodePtr parent, xmlNodePtr cur, gboolean trusted); void (*export) (nodePtr node, xmlNodePtr cur, gboolean trusted); itemSetPtr (*load) (nodePtr node); void (*save) (nodePtr node); void (*update_counters) (nodePtr node); void (*process_update_result)(nodePtr node, const struct updateResult * const result, updateFlags flags); void (*remove) (nodePtr node); gchar * (*render) (nodePtr node); void (*request_add) (nodePtr parent); void (*request_properties) (nodePtr node); /** * Called to allow node type to clean up it's specific data. * The node structure itself is destroyed after this call. * * @param node the node */ void (*free) (nodePtr node); } *nodeTypePtr;
我们先来实现定义feed类型:
feed.c:
nodeTypePtr feed_get_node_type (void) { static struct nodeType nti = { NODE_CAPABILITY_SHOW_UNREAD_COUNT | NODE_CAPABILITY_UPDATE, "feed", /* not used, feed format ids are used instead */ NULL, feed_import, feed_export, feed_load, feed_save, feed_update_unread_count, feed_process_update_result, feed_remove, feed_render, feed_add, feed_properties, feed_free }; nti.icon = icons[ICON_DEFAULT]; return &nti; } // 函数实现 static void feed_save (nodePtr node) { /* Nothing to do. Feeds do not have any UI states */ } static void feed_update_unread_count (nodePtr node) { node->itemCount = db_itemset_get_item_count (node->id); node->unreadCount = db_itemset_get_unread_count (node->id); } static void feed_remove (nodePtr node) { notification_node_removed (node); ui_node_remove_node (node); favicon_remove_from_cache (node->id); db_subscription_remove (node->id); } ...//数据结构中其余函数的实现
在集合类中进行类型注册:
feedlist.c
void feedlist_init(void) { debug_enter("feedlist_init"); /* 1. Register standard node and source types */ node_type_register (feed_get_node_type ()); node_type_register (root_get_node_type ()); node_type_register (folder_get_node_type ()); node_type_register (vfolder_get_node_type ()); node_type_register (node_source_get_node_type ()); node_type_register (newsbin_get_node_type ()); node_source_type_register (default_source_get_type ()); node_source_type_register (dummy_source_get_type ()); node_source_type_register (opml_source_get_type ()); node_source_type_register (bloglines_source_get_type ()); node_source_type_register (google_source_get_type ()); ...// 省略 }
类型注册实现函数:
node_type.c
static GSList *nodeTypes = NULL; void node_type_register (nodeTypePtr nodeType) { /* all attributes and methods are mandatory! */ g_assert (nodeType->id); g_assert (nodeType->import); g_assert (nodeType->export); g_assert (nodeType->load); g_assert (nodeType->save); g_assert (nodeType->update_counters); g_assert (nodeType->remove); g_assert (nodeType->render); g_assert (nodeType->request_add); g_assert (nodeType->request_properties); nodeTypes = g_slist_append (nodeTypes, (gpointer)nodeType); } void node_set_type (nodePtr node, nodeTypePtr type) { node->type = type; } const gchar * node_type_to_str (nodePtr node) { if (IS_FEED (node)) { g_assert (NULL != node->data); return feed_type_fhp_to_str (((feedPtr)(node->data))->fhp); } return NODE_TYPE (node)->id; } nodeTypePtr node_str_to_type (const gchar *str) { GSList *iter = nodeTypes; g_assert (NULL != str); if (g_str_equal (str, "")) /* type maybe "" if initial download is not yet done */ return feed_get_node_type (); if (NULL != feed_type_str_to_fhp (str)) return feed_get_node_type (); /* check against all node types */ while (iter) { if (g_str_equal (str, ((nodeTypePtr)iter->data)->id)) return (nodeTypePtr)iter->data; iter = g_slist_next (iter); } return NULL; } /* Interactive node adding (e.g. feed menu->new subscription) */ void node_type_request_interactive_add (nodeTypePtr nodeType) { nodePtr parent; parent = feedlist_get_insertion_point (); if (0 == (NODE_TYPE (parent->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS)) return; nodeType->request_add (parent); }
需要调用类型的时候,使用node_set_type(node, str)函数,比如:
nodeTypePtr node_type = node_str_to_type(“feed”);