代码摘自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:
nodeTypePtrfeed_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 voidfeed_save (nodePtr node){ /* Nothing to do. Feeds do not have any UI states */}static voidfeed_update_unread_count (nodePtr node){ node->itemCount = db_itemset_get_item_count (node->id); node->unreadCount = db_itemset_get_unread_count (node->id);}static voidfeed_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);}voidnode_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;}nodeTypePtrnode_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) */voidnode_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”);?