实现类似GOBJECT类型注册功能(XXX_type_register)

代码摘自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”);
 

你可能感兴趣的:(数据结构,C++,c,UI,C#)