gnome-logs开发记录4--noob重构代码就是这个feel

来源:互联网 发布:做淘宝被监督管理局查 编辑:程序博客网 时间:2024/04/28 03:42

bug链接:https://bugzilla.gnome.org/show_bug.cgi?id=726228


只记得贡献了第一次代码后,在bugzilla中找来找去,不知怎么就选上了这个任务。或许是表面上看着很简单吧。至少现在看来我是大错特错了。

当时自己确定要修复这个bug时,就给David发了一封邮件,告知他我的意愿。David在回信中谈到了他自己对这个bug的认识,如下:

My suggestion would be to create a new GlEventView widget, which would be a stack which switches between the category list/event list view and the details view. It might be a bit complex to disentangle the code, especially the signal propagation during view mode changes, but the majority of the patch should be moving code from one file to another.

当然,对于我这么一个newbie来说,这些解释肯定是对我的帮助不太大的。通过之后和David的交流,我算是向前买了一小步。当然这一段时间,自己也算是摸不着北地摸索了很久,笔记本又增加了若干页墨迹的重量。

之前程序中构件等级是这样的:

window

->category list

->stack

    ->event list view

    ->detail view

目标是这样:

window

->stack

    ->events view (GlEventView)

        ->category list

        ->event list view

    ->detail view

又是几页的墨迹,我来到了这一步:自己画了一个简图,有了三步走计划

简图

三步走计划:

  The first: make event list view a GtkBox

  The second: create a GtkBox named event_view to contain category list and event list view

  The third: create a GtkStack named GlEventView which contains event_view and detail view


So,我目标很明确。照着这三步,一个个实现就一定ok了。当时是这么想的,不过后来发现我错了。

虽然目标明确,但我还是不知从哪里下手,比如在哪里改动UI等。就这么在这几天学习了一些关于signal、GValue、GAction等知识,虽然是一知半解,没有完全明白。


再往后,弄明白了一共需要两个GtkStack来处理页面转换。一个是GlEventView,另一个是GlEventViewList(当时这么理解,其实GlEventViewList应该是GtkBox)。

当然这期间,自己一直在做的一件事情就是用g_print() 输出一些辅助信息来帮助自己理解整个程序是怎么运行的。比如说,打开程序和我点击某一个event view list row后什么函数会被调用和其间的顺序。


再往后,就到了一个转折点。

我终于明白了新建一个GlEventView是要新建一个类,需要新建.c、.h和一个.ui文件。一个月就这么过去了,已经10月14日了。

在这里记录下这个邮件:

Hi David
    I think I get the idea about fixing the bug. For such a long time, I was heading a wrong direction.
    I should create a type named GlEventView which is a stack, and move the some parts of the existing stack GlEventViewList to GlEventView. Then I should do the things we discussed days ago, like making GlCategoryList and GlEventViewList in the same widget, etc. Am I right? I think finally I get the right idea about it.


之后遇到的一个很棘手的问题是关于类的调用问题,比如说我想在gl-eventview.c中调用GlEventViewList这个类的指针。

在这里详细解释下这个问题。

在C++中,如果在一个类A的实现中需要调用另一个类B的话,一般我们只要生成一个B类的对象或者指针就可以。但是在Gnome开发中就不可以这样了。因为一个类就对应着一个widget,重新生成是无法解决问题的。其实这里涉及到一个知识,那就是在Gnome开发中,一个widget对应的类只能操作其的子类。而这个父子关系是通过.ui文件来实现的。

我提交的patch中gl-eventview.ui文件内容如下:

<interface domain="gnome-logs">
    <template class="GlEventView" parent="GtkStack">
        <property name="visible">True</property>
        <child>
            <object class="GlEventViewList" id="events">
                <property name="visible">True</property>
            </object>
        </child>
    </template>
</interface>

这个.ui 文件是描述GlEventView的布局,<child>标签就说明了GlEventViewList是GlEventView的子类。然后如果我想在gl-eventview.c中想要用到GlEventViewList的话,我还需要做些工作。那就是在GlEventViewPrivate中添加一个条目GtkWidget *events;。在gl_event_view_class_init中使用下面两个语句来将GlEventViewList和events绑定:

gtk_widget_class_set_template_from_resource (widget_class,
                                                 "/org/gnome/Logs/gl-eventview.ui");
    gtk_widget_class_bind_template_child_private (widget_class, GlEventView,
                                                  events);

在这里有一点需要注意.ui文件中GlEventViewList的id要和GlEventViewPrivate中widget的名字一样。如此一来,我们就将GlEventViewList和GtkWidget *events绑定。想要用到GlEventViewList的指针时,需要以下的代码:

    GlEventViewPrivate *priv;
    GlEventViewList *events;

    priv = gl_event_view_get_instance_private (view);
    events = GL_EVENT_VIEW_LIST (priv->events);

这么以来events就是GlEventViewList的指针了。


到此,进度还不到三分之一。

今天就先写到这里吧。

0 0