Merge lp://qastaging/~ted/libindicator/loader into lp://qastaging/libindicator/0.4

Proposed by Ted Gould
Status: Merged
Merged at revision: not available
Proposed branch: lp://qastaging/~ted/libindicator/loader
Merge into: lp://qastaging/libindicator/0.4
Diff against target: 752 lines
12 files modified
.bzrignore (+14/-0)
Makefile.am (+3/-1)
configure.ac (+15/-0)
libindicator/Makefile.am (+16/-1)
libindicator/indicator-object.c (+290/-0)
libindicator/indicator-object.h (+61/-0)
tests/Makefile.am (+92/-0)
tests/dummy-indicator-blank.c (+6/-0)
tests/dummy-indicator-null.c (+23/-0)
tests/dummy-indicator-simple.c (+28/-0)
tests/test-loader.c (+109/-0)
tools/Makefile.am (+1/-0)
To merge this branch: bzr merge lp://qastaging/~ted/libindicator/loader
Reviewer Review Type Date Requested Status
Robert Collins (community) Needs Fixing
Review via email: mp+14117@code.qastaging.launchpad.net
To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

Implements a basic loader that is stolen from indicator-applet. This should put it all in one place, for everyone.

Revision history for this message
Robert Collins (lifeless) wrote :

107 +An interface for indicators to link to for creation.
108 +

This is brief to the point of being opaque.

135 +/**
136 + IndicatorObjectPrivate:
137 + @label: The label representing this indicator or #NULL if none.
138 + @icon: The icon representing this indicator or #NULL if none.
139 + @menu: The menu representing this indicator or #NULL if none.
140 +
141 + Private data for the object.
142 +*/

Is this private for libindicator or private for subclasses - I assume private for libindicator, but a little more clarity would help.

175 +/* Inititalize an instance */

Typo

 +static void
215 +indicator_object_finalize (GObject *object)
216 +{
217 +
218 + G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object);
219 + return;
220 +}

return here is noise.

271 + /* A this point we allocate the object, any code beyond
272 + here needs to deallocate it if we're returning in an
273 + error'd state. */
274 + GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL);
275 + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
276 +
277 + /* The function for grabbing a label from the module
278 + execute it, and make sure everything is a-okay */
279 + get_label_t lget_label = NULL;
280 + if (!g_module_symbol(module, INDICATOR_GET_LABEL_S, (gpointer *)(&lget_label))) {
281 + g_warning("Unable to get '" INDICATOR_GET_LABEL_S "' symbol from module: %s", file);
282 + goto unrefandout;
283 + }
284 + if (lget_label == NULL) {

I prefer to put constants on the left in if statements, it makes typos like 'lget_label = NULL' more visually distinctive. Up to you though.

341 +/**
342 + indicator_object_get_label:
343 + @io: An #IndicatorObject.
344 +
345 + A function to get the label for a particular object. This
346 + function does not increase the refcount. That's your job
347 + if you want to do it.

Thats an uncommon idiom isn't it, in gtk land? Perhaps making this clear in the name would help (append _unreffed)? If I'm wrong then its fine as-is, of course.

377 +/**
378 + indicator_object_get_menu:
379 + @io: An #IndicatorObject.
380 +
381 + A function to get the menu for a particular object. This
382 + function does not increase the refcount. That's your job
383 + if you want to do it.

Ditto.

395 === added file 'libindicator/indicator-object.h'
396 --- libindicator/indicator-object.h 1970-01-01 00:00:00 +0000
397 +++ libindicator/indicator-object.h 2009-10-28 21:50:22 +0000
398 @@ -0,0 +1,60 @@
399 +/*
400 +An interface for indicators to link to for creation.

Same comment about clarity ;)

Tests look good.

The tools/* directory seems unused, is it needed?

744 === added directory 'tools'
745 === added file 'tools/Makefile.am'
746 --- tools/Makefile.am 1970-01-01 00:00:00 +0000
747 +++ tools/Makefile.am 2009-10-28 21:50:22 +0000
748 @@ -0,0 +1,1 @@
749 +#Something

Overall good, some things to tweak/improve then +1

review: Needs Fixing
Revision history for this message
Ted Gould (ted) wrote :
Download full text (4.5 KiB)

On Tue, 2009-11-03 at 02:19 +0000, Robert Collins wrote:
> Review: Needs Fixing
> 107 +An interface for indicators to link to for creation.
> 108 +
>
> This is brief to the point of being opaque.

Fixed r368.

> 135 +/**
> 136 + IndicatorObjectPrivate:
> 137 + @label: The label representing this indicator or #NULL if none.
> 138 + @icon: The icon representing this indicator or #NULL if none.
> 139 + @menu: The menu representing this indicator or #NULL if none.
> 140 +
> 141 + Private data for the object.
> 142 +*/
>
> Is this private for libindicator or private for subclasses - I assume
> private for libindicator, but a little more clarity would help.

It's private for the object. Almost all GObject objects have this
private data area that is created on a per-instance area. It's a way to
have private variables in C based objects :)

> 175 +/* Inititalize an instance */
>
> Typo

Fixed r369

> +static void
> 215 +indicator_object_finalize (GObject *object)
> 216 +{
> 217 +
> 218 + G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object);
> 219 + return;
> 220 +}
>
> return here is noise.

I'd actually argue the opposite. I'd argue that functions without
returns mean that you didn't think about how the function ends. In
reality, that whole function is noise, but it's part of the GTK
boilerplate because it's a pain to create when you do need it.

> 271 + /* A this point we allocate the object, any code beyond
> 272 + here needs to deallocate it if we're returning in an
> 273 + error'd state. */
> 274 + GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL);
> 275 + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
> 276 +
> 277 + /* The function for grabbing a label from the module
> 278 + execute it, and make sure everything is a-okay */
> 279 + get_label_t lget_label = NULL;
> 280 + if (!g_module_symbol(module, INDICATOR_GET_LABEL_S, (gpointer *)(&lget_label))) {
> 281 + g_warning("Unable to get '" INDICATOR_GET_LABEL_S "' symbol from module: %s", file);
> 282 + goto unrefandout;
> 283 + }
> 284 + if (lget_label == NULL) {
>
> I prefer to put constants on the left in if statements, it makes typos
> like 'lget_label = NULL' more visually distinctive. Up to you though.

I like them being on the right because I think it makes the code easier
to read. If I was explaining it to you in English I would say "If the
label is NULL" not "If NULL was the value of the label." In general, if
people have to think to much about the code, I think they're likely to
make more mistakes rather than less.

In the end, this is why I've been advocating use working with the
Coverity folks. I really want LP integration there. Sadly, I think I'm
the only one that's really excited about it :(

> 341 +/**
> 342 + indicator_object_get_label:
> 343 + @io: An #IndicatorObject.
> 344 +
> 345 + A function to get the label for a particular object. This
> 346 + function does not increase the refcount. That's your job
> 347 + if you want to do it.
>
> Thats an uncommon idiom isn't it, in gtk land? Perhaps making this
> clear in the name would help (append _unreffed)? If I'm wrong then
> its fine as-is, of course.

Unfortunate...

Read more...

Revision history for this message
Cody Russell (bratsche) wrote :

> 135 +/**
> 136 + IndicatorObjectPrivate:
> 137 + @label: The label representing this indicator or #NULL if none.
> 138 + @icon: The icon representing this indicator or #NULL if none.
> 139 + @menu: The menu representing this indicator or #NULL if none.
> 140 +
> 141 + Private data for the object.
> 142 +*/
>
> Is this private for libindicator or private for subclasses - I assume private
> for libindicator, but a little more clarity would help.

This is GObject-fu. It's the private data for an object, in order to keep it out of public structs. However, Ted, I think that we're all using this in a slightly sub-optimal way and perhaps it would be good to start switching the style that we use this.

Right now we've been defining FooPrivate in the .c file, and whenever it's needed we use FOO_GET_PRIVATE() in a function. Now that we're starting to move sealed items into private data in gtk+ the way we're doing it is to typedef this struct in the .h file and then have a pointer to it in FooObject...

typedef struct _FooObject FooObject;
typedef struct _FooObjectPrivate FooObjectPrivate;
struct _FooObject
{
   GObject parent_object;
   FooObjectPrivate *priv;
};

Then in the .c file, foo_object_init() sets obj->priv = FOO_OBJECT_GET_PRIVATE(obj);

The reason is that FOO_OBJECT_GET_PRIVATE() is much slower than just doing foo->priv. So I'm starting to switch over to using this style.

> 218 + G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object);
> 219 + return;
> 220 +}
>
> return here is noise.

woot! :)

> 284 + if (lget_label == NULL) {
>
> I prefer to put constants on the left in if statements, it makes typos like
> 'lget_label = NULL' more visually distinctive. Up to you though.

Putting constants on the right is pretty much the style that's used everywhere in the desktop modules though. I understand the rationale here, but I'd rather Ted keep this the way he has it for consistency.

> 345 + A function to get the label for a particular object. This
> 346 + function does not increase the refcount. That's your job
> 347 + if you want to do it.
>
> Thats an uncommon idiom isn't it, in gtk land? Perhaps making this clear in
> the name would help (append _unreffed)? If I'm wrong then its fine as-is, of
> course.

I think it kind of depends on what's being returned and what it's likely to be returned for. If he's returning a widget, it's usually to either operate on it (e.g., set the label's text) or to insert it into a container or something. In the first case you don't want to retrieve a widget, do some operation, and then unref it. In the second case your container will ref it.

368. By Ted Gould

Comments in the copyright statements updated.

369. By Ted Gould

Typo

Revision history for this message
Robert Collins (lifeless) wrote :
Download full text (3.1 KiB)

On Tue, 2009-11-03 at 16:18 +0000, Ted Gould wrote:
>
> > Is this private for libindicator or private for subclasses - I
> assume
> > private for libindicator, but a little more clarity would help.
>
> It's private for the object. Almost all GObject objects have this
> private data area that is created on a per-instance area. It's a way
> to
> have private variables in C based objects :)

Oh, yes I *know* that; what I mean is that the comment was too brief:
even for common idioms, unless there is too high a cost to do so, we
should aim for clarity.

It was the 'private data for this object' that was a little unclear -
not hugely so but I had to read it twice to be sure.

> > +static void
> > 215 +indicator_object_finalize (GObject *object)
> > 216 +{
> > 217 +
> > 218 + G_OBJECT_CLASS (indicator_object_parent_class)->finalize
> (object);
> > 219 + return;
> > 220 +}
> >
> > return here is noise.
>
> I'd actually argue the opposite. I'd argue that functions without
> returns mean that you didn't think about how the function ends. In
> reality, that whole function is noise, but it's part of the GTK
> boilerplate because it's a pain to create when you do need it.

I see Cody agree's with me :). A function that returns void, returns
void - it *is* noise to add a return there, because you /cannot/ return
anything. I'll accept your point in a function that returns non-void
(and so will compilers :)).

> In the end, this is why I've been advocating use working with the
> Coverity folks. I really want LP integration there. Sadly, I think
> I'm
> the only one that's really excited about it :(

That would rock! foo == NULL is fine, it was just an observation.

> > 341 +/**
> > 342 + indicator_object_get_label:
> > 343 + @io: An #IndicatorObject.
> > 344 +
> > 345 + A function to get the label for a particular object. This
> > 346 + function does not increase the refcount. That's your job
> > 347 + if you want to do it.
> >
> > Thats an uncommon idiom isn't it, in gtk land? Perhaps making this
> > clear in the name would help (append _unreffed)? If I'm wrong then
> > its fine as-is, of course.
>
> Unfortunately, it's rather inconsistent. But, since the common usage
> of
> this should be grabbing it and putting it into a container widget. So
> it'd only force an unref in the calling application and increase the
> chance of a runaway count.

Would it be horrible to *signal* that this does not take a ref:
indicator_object_get_label_(steal|unref|noref|...) ?

> > 377 +/**
> > 378 + indicator_object_get_menu:
> > 379 + @io: An #IndicatorObject.
> > 380 +
> > 381 + A function to get the menu for a particular object. This
> > 382 + function does not increase the refcount. That's your job
> > 383 + if you want to do it.
> >
> > Ditto.
>
> Ditto.

Ditto. :)

> > The tools/* directory seems unused, is it needed?

> Not currently. I had expected to do more with this branch, but since
> priorities got rescheduled it had to be cut back :( It should be used
> in the future hopefully as all the other indicators can't really be
> tested effectively until there is a loader tool that allows for
> test...

Read more...

Revision history for this message
Robert Collins (lifeless) wrote :

On Tue, 2009-11-03 at 15:54 +0000, Cody Russell wrote:
> > 135 +/**
> > 136 + IndicatorObjectPrivate:
> > 137 + @label: The label representing this indicator or #NULL if none.
> > 138 + @icon: The icon representing this indicator or #NULL if none.
> > 139 + @menu: The menu representing this indicator or #NULL if none.
> > 140 +
> > 141 + Private data for the object.
> > 142 +*/
> >
> > Is this private for libindicator or private for subclasses - I assume private
> > for libindicator, but a little more clarity would help.
>
> This is GObject-fu. It's the private data for an object, in order to keep it out of public structs. However, Ted, I think that we're all using this in a slightly sub-optimal way and perhaps it would be good to start switching the style that we use this.
>
> Right now we've been defining FooPrivate in the .c file, and whenever it's needed we use FOO_GET_PRIVATE() in a function. Now that we're starting to move sealed items into private data in gtk+ the way we're doing it is to typedef this struct in the .h file and then have a pointer to it in FooObject...
>
> typedef struct _FooObject FooObject;
> typedef struct _FooObjectPrivate FooObjectPrivate;
> struct _FooObject
> {
> GObject parent_object;
> FooObjectPrivate *priv;
> };
>
> Then in the .c file, foo_object_init() sets obj->priv = FOO_OBJECT_GET_PRIVATE(obj);
>
>
> The reason is that FOO_OBJECT_GET_PRIVATE() is much slower than just doing foo->priv. So I'm starting to switch over to using this style.

This works fine for me.

-Rob

Revision history for this message
Ted Gould (ted) wrote :

On Tue, 2009-11-03 at 22:45 +0000, Robert Collins wrote:
> On Tue, 2009-11-03 at 15:54 +0000, Cody Russell wrote:
> > > 135 +/**
> > > 136 + IndicatorObjectPrivate:
> > > 137 + @label: The label representing this indicator or #NULL if none.
> > > 138 + @icon: The icon representing this indicator or #NULL if none.
> > > 139 + @menu: The menu representing this indicator or #NULL if none.
> > > 140 +
> > > 141 + Private data for the object.
> > > 142 +*/
> > >
> > > Is this private for libindicator or private for subclasses - I assume private
> > > for libindicator, but a little more clarity would help.
> >
> > This is GObject-fu. It's the private data for an object, in order to keep it out of public structs. However, Ted, I think that we're all using this in a slightly sub-optimal way and perhaps it would be good to start switching the style that we use this.
> >
> > Right now we've been defining FooPrivate in the .c file, and whenever it's needed we use FOO_GET_PRIVATE() in a function. Now that we're starting to move sealed items into private data in gtk+ the way we're doing it is to typedef this struct in the .h file and then have a pointer to it in FooObject...
> >
> > typedef struct _FooObject FooObject;
> > typedef struct _FooObjectPrivate FooObjectPrivate;
> > struct _FooObject
> > {
> > GObject parent_object;
> > FooObjectPrivate *priv;
> > };
> >
> > Then in the .c file, foo_object_init() sets obj->priv = FOO_OBJECT_GET_PRIVATE(obj);
> >
> >
> > The reason is that FOO_OBJECT_GET_PRIVATE() is much slower than just doing foo->priv. So I'm starting to switch over to using this style.
>
> This works fine for me.

Let's do this for new objects, I don't see a reason to modify older ones
to do it.

  --Ted

370. By Ted Gould

Changing comment on private struct.

Revision history for this message
Ted Gould (ted) wrote :
Download full text (3.3 KiB)

On Tue, 2009-11-03 at 22:42 +0000, Robert Collins wrote:
> On Tue, 2009-11-03 at 16:18 +0000, Ted Gould wrote:
> >
> > > Is this private for libindicator or private for subclasses - I
> > assume
> > > private for libindicator, but a little more clarity would help.
> >
> > It's private for the object. Almost all GObject objects have this
> > private data area that is created on a per-instance area. It's a way
> > to
> > have private variables in C based objects :)
>
> Oh, yes I *know* that; what I mean is that the comment was too brief:
> even for common idioms, unless there is too high a cost to do so, we
> should aim for clarity.
>
> It was the 'private data for this object' that was a little unclear -
> not hugely so but I had to read it twice to be sure.

r370

> > > +static void
> > > 215 +indicator_object_finalize (GObject *object)
> > > 216 +{
> > > 217 +
> > > 218 + G_OBJECT_CLASS (indicator_object_parent_class)->finalize
> > (object);
> > > 219 + return;
> > > 220 +}
> > >
> > > return here is noise.
> >
> > I'd actually argue the opposite. I'd argue that functions without
> > returns mean that you didn't think about how the function ends. In
> > reality, that whole function is noise, but it's part of the GTK
> > boilerplate because it's a pain to create when you do need it.
>
> I see Cody agree's with me :). A function that returns void, returns
> void - it *is* noise to add a return there, because you /cannot/ return
> anything. I'll accept your point in a function that returns non-void
> (and so will compilers :)).

No, it's explicitly stating something that is otherwise implicit. For
instance the return has value in a situation like this, even though no
value is returned.

void
myfunc (void * myvar) {
  if (myvar == NULL)
    return;

  /* do stuff */

  return;
}

Both of them have value because they're both signaling points where the
function would end. Likewise something like this would provide value:

void
myfunc (void * myvar) {
  if (myvar == NULL)
    goto end;

  /* do stuff */

  return;
end:
  g_warning("NULL input");
  return;
}

You're just counting on the '}' at the end of the function putting an
implied return there. I'm saying we should be explicit about the ending
of a function because it's a very important thing in the function.

> > > 341 +/**
> > > 342 + indicator_object_get_label:
> > > 343 + @io: An #IndicatorObject.
> > > 344 +
> > > 345 + A function to get the label for a particular object. This
> > > 346 + function does not increase the refcount. That's your job
> > > 347 + if you want to do it.
> > >
> > > Thats an uncommon idiom isn't it, in gtk land? Perhaps making this
> > > clear in the name would help (append _unreffed)? If I'm wrong then
> > > its fine as-is, of course.
> >
> > Unfortunately, it's rather inconsistent. But, since the common usage
> > of
> > this should be grabbing it and putting it into a container widget. So
> > it'd only force an unref in the calling application and increase the
> > chance of a runaway count.
>
> Would it be horrible to *signal* that this does not take a ref:
> indicator_object_get_label_(steal|unref|noref|...) ...

Read more...

Revision history for this message
Robert Collins (lifeless) wrote :

On Tue, 2009-11-03 at 23:15 +0000, Ted Gould wrote:

> > I see Cody agree's with me :). A function that returns void, returns
> > void - it *is* noise to add a return there, because you /cannot/ return
> > anything. I'll accept your point in a function that returns non-void
> > (and so will compilers :)).
>
> No, it's explicitly stating something that is otherwise implicit. For
> instance the return has value in a situation like this, even though no
> value is returned.
...
> You're just counting on the '}' at the end of the function putting an
> implied return there. I'm saying we should be explicit about the ending
> of a function because it's a very important thing in the function.

I can see you feel strongly about this; I'm sure it will turn up in
reviews again. So far you haven't convinced Cody or myself. Its a very
idiosyncratic coding style.

I have no objection to you landing this patch with it like that, but I
think this bears more discussion: having other folk cringe every time
they see a return at the end of a function isn't great :)

> > Would it be horrible to *signal* that this does not take a ref:
> > indicator_object_get_label_(steal|unref|noref|...) ?
>
> I'd agree, but I think with out guidance from GTK/Glib I'm not sure that
> it'd be that useful. Personally, I'd rather go with _ref on functions
> that do create refs.

Lets land this branch. Perhaps you could blog (you are on planet gnome,
yes?) about this and see if there is any major feelings from the
community?

Adding _ref works fine for me too - I don't care about the specific
representation of the signal, just the presence.

-Rob

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2009-08-07 15:06:32 +0000
3+++ .bzrignore 2009-11-03 23:08:11 +0000
4@@ -103,3 +103,17 @@
5 data/GNOME_IndicatorAppletSUS.server
6 data/GNOME_IndicatorAppletSUS.server.in
7 src-sus/indicator-applet-no-sus
8+libindicator/libindicator.la
9+libindicator/libindicator_la-indicator-object.
10+libindicator/libindicator_la-indicator-object.lo
11+tests/loader-check-results.xml
12+tests/loader-check-results.html
13+tests/test-loader
14+tests/libdummy-indicator-null.la
15+tests/libdummy_indicator_null_la-dummy-indicator-null.lo
16+tests/libdummy-indicator-simple.la
17+tests/libdummy_indicator_simple_la-dummy-indicator-simple.lo
18+tests/libdummy-indicator-blank.la
19+tests/libdummy_indicator_blank_la-dummy-indicator-blank.lo
20+libindicator-[0-9].[0-9].[0-9].tar.gz
21+libindicator-[0-9].[0-9].[0-9].tar.gz.asc
22
23=== modified file 'Makefile.am'
24--- Makefile.am 2009-08-18 16:52:09 +0000
25+++ Makefile.am 2009-11-03 23:08:11 +0000
26@@ -1,6 +1,8 @@
27
28 SUBDIRS = \
29- libindicator
30+ libindicator \
31+ tests \
32+ tools
33
34 DISTCLEANFILES = \
35 libindicator-*.tar.gz
36
37=== modified file 'configure.ac'
38--- configure.ac 2009-10-08 14:11:01 +0000
39+++ configure.ac 2009-11-03 23:08:11 +0000
40@@ -21,6 +21,19 @@
41 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
42
43 ##############################
44+# Dependencies
45+##############################
46+
47+GTK_REQUIRED_VERSION=2.18
48+DBUS_REQUIRED_VERSION=0.76
49+
50+PKG_CHECK_MODULES(LIBINDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
51+ dbus-glib-1 >= $DBUS_REQUIRED_VERSION)
52+
53+AC_SUBST(LIBINDICATOR_CFLAGS)
54+AC_SUBST(LIBINDICATOR_LIBS)
55+
56+##############################
57 # Custom Junk
58 ##############################
59
60@@ -73,6 +86,8 @@
61 Makefile
62 libindicator/Makefile
63 libindicator/indicator.pc
64+tests/Makefile
65+tools/Makefile
66 ])
67
68 ###########################
69
70=== modified file 'libindicator/Makefile.am'
71--- libindicator/Makefile.am 2009-04-21 19:15:22 +0000
72+++ libindicator/Makefile.am 2009-11-03 23:08:11 +0000
73@@ -4,11 +4,26 @@
74 libindicatorincludedir=$(includedir)/libindicator-0.1/libindicator
75
76 indicator_headers = \
77- indicator.h
78+ indicator.h \
79+ indicator-object.h
80
81 libindicatorinclude_HEADERS = \
82 $(indicator_headers)
83
84+lib_LTLIBRARIES = \
85+ libindicator.la
86+
87+libindicator_la_SOURCES = \
88+ $(indicator_headers) \
89+ indicator-object.c
90+
91+libindicator_la_CFLAGS = \
92+ $(LIBINDICATOR_CFLAGS) \
93+ -Wall -Werror
94+
95+libindicator_la_LIBADD = \
96+ $(LIBINDICATOR_LIBS)
97+
98 pkgconfig_DATA = indicator.pc
99 pkgconfigdir = $(libdir)/pkgconfig
100
101
102=== added file 'libindicator/indicator-object.c'
103--- libindicator/indicator-object.c 1970-01-01 00:00:00 +0000
104+++ libindicator/indicator-object.c 2009-11-03 23:08:11 +0000
105@@ -0,0 +1,290 @@
106+/*
107+An object to represent loadable indicator modules to make loading
108+them easy and objectified.
109+
110+Copyright 2009 Canonical Ltd.
111+
112+Authors:
113+ Ted Gould <ted@canonical.com>
114+
115+This library is free software; you can redistribute it and/or
116+modify it under the terms of the GNU General Public License
117+version 3.0 as published by the Free Software Foundation.
118+
119+This library is distributed in the hope that it will be useful,
120+but WITHOUT ANY WARRANTY; without even the implied warranty of
121+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
122+GNU General Public License version 3.0 for more details.
123+
124+You should have received a copy of the GNU General Public
125+License along with this library. If not, see
126+<http://www.gnu.org/licenses/>.
127+*/
128+
129+#ifdef HAVE_CONFIG_H
130+#include "config.h"
131+#endif
132+
133+#include "indicator.h"
134+#include "indicator-object.h"
135+
136+/**
137+ IndicatorObjectPrivate:
138+ @label: The label representing this indicator or #NULL if none.
139+ @icon: The icon representing this indicator or #NULL if none.
140+ @menu: The menu representing this indicator or #NULL if none.
141+
142+ Structure to define the memory for the private area
143+ of the object instance.
144+*/
145+typedef struct _IndicatorObjectPrivate IndicatorObjectPrivate;
146+struct _IndicatorObjectPrivate {
147+ GtkLabel * label;
148+ GtkImage * icon;
149+ GtkMenu * menu;
150+};
151+
152+#define INDICATOR_OBJECT_GET_PRIVATE(o) \
153+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_OBJECT_TYPE, IndicatorObjectPrivate))
154+
155+static void indicator_object_class_init (IndicatorObjectClass *klass);
156+static void indicator_object_init (IndicatorObject *self);
157+static void indicator_object_dispose (GObject *object);
158+static void indicator_object_finalize (GObject *object);
159+
160+G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT);
161+
162+/* Setup the class and put the functions into the
163+ class structure */
164+static void
165+indicator_object_class_init (IndicatorObjectClass *klass)
166+{
167+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
168+
169+ g_type_class_add_private (klass, sizeof (IndicatorObjectPrivate));
170+
171+ object_class->dispose = indicator_object_dispose;
172+ object_class->finalize = indicator_object_finalize;
173+
174+ return;
175+}
176+
177+/* Initialize an instance */
178+static void
179+indicator_object_init (IndicatorObject *self)
180+{
181+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(self);
182+
183+ priv->label = NULL;
184+ priv->icon = NULL;
185+ priv->menu = NULL;
186+
187+ return;
188+}
189+
190+/* Unref the objects that we're holding on to. */
191+static void
192+indicator_object_dispose (GObject *object)
193+{
194+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
195+
196+ if (priv->label != NULL) {
197+ g_object_unref(priv->label);
198+ priv->label = NULL;
199+ }
200+
201+ if (priv->icon != NULL) {
202+ g_object_unref(priv->icon);
203+ priv->icon = NULL;
204+ }
205+
206+ if (priv->menu != NULL) {
207+ g_object_unref(priv->menu);
208+ priv->menu = NULL;
209+ }
210+
211+ G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object);
212+ return;
213+}
214+
215+/* Free memory */
216+static void
217+indicator_object_finalize (GObject *object)
218+{
219+
220+ G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object);
221+ return;
222+}
223+
224+/**
225+ indicator_object_new_from_file:
226+ @file: Filename containing a loadable module
227+
228+ This function builds an #IndicatorObject using the symbols
229+ that are found in @file. The module is loaded and the
230+ references are all kept by the object. To unload the
231+ module the object must be destroyed.
232+
233+ Return value: A valid #IndicatorObject or #NULL if error.
234+*/
235+IndicatorObject *
236+indicator_object_new_from_file (const gchar * file)
237+{
238+ /* Check to make sure the name exists and that the
239+ file itself exists */
240+ if (file == NULL) {
241+ g_warning("Invalid filename.");
242+ return NULL;
243+ }
244+
245+ if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
246+ g_warning("File '%s' does not exist.", file);
247+ return NULL;
248+ }
249+
250+ /* Grab the g_module reference, pull it in but let's
251+ keep the symbols local to avoid conflicts. */
252+ GModule * module = g_module_open(file,
253+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
254+ if(module == NULL) {
255+ g_warning("Unable to load module: %s", file);
256+ return NULL;
257+ }
258+
259+ /* Look for the version function, error if not found. */
260+ get_version_t lget_version = NULL;
261+ if (!g_module_symbol(module, INDICATOR_GET_VERSION_S, (gpointer *)(&lget_version))) {
262+ g_warning("Unable to get the symbol for getting the version.");
263+ return NULL;
264+ }
265+
266+ /* Check the version with the macro and make sure we're
267+ all talking the same language. */
268+ if (!INDICATOR_VERSION_CHECK(lget_version())) {
269+ g_warning("Indicator using API version '%s' we're expecting '%s'", lget_version(), INDICATOR_VERSION);
270+ return NULL;
271+ }
272+
273+ /* A this point we allocate the object, any code beyond
274+ here needs to deallocate it if we're returning in an
275+ error'd state. */
276+ GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL);
277+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
278+
279+ /* The function for grabbing a label from the module
280+ execute it, and make sure everything is a-okay */
281+ get_label_t lget_label = NULL;
282+ if (!g_module_symbol(module, INDICATOR_GET_LABEL_S, (gpointer *)(&lget_label))) {
283+ g_warning("Unable to get '" INDICATOR_GET_LABEL_S "' symbol from module: %s", file);
284+ goto unrefandout;
285+ }
286+ if (lget_label == NULL) {
287+ g_warning("Symbol '" INDICATOR_GET_LABEL_S "' is (null) in module: %s", file);
288+ goto unrefandout;
289+ }
290+ priv->label = lget_label();
291+ if (priv->label) {
292+ g_object_ref(G_OBJECT(priv->label));
293+ }
294+
295+ /* The function for grabbing an icon from the module
296+ execute it, and make sure everything is a-okay */
297+ get_icon_t lget_icon = NULL;
298+ if (!g_module_symbol(module, INDICATOR_GET_ICON_S, (gpointer *)(&lget_icon))) {
299+ g_warning("Unable to get '" INDICATOR_GET_ICON_S "' symbol from module: %s", file);
300+ goto unrefandout;
301+ }
302+ if (lget_icon == NULL) {
303+ g_warning("Symbol '" INDICATOR_GET_ICON_S "' is (null) in module: %s", file);
304+ goto unrefandout;
305+ }
306+ priv->icon = lget_icon();
307+ if (priv->icon) {
308+ g_object_ref(G_OBJECT(priv->icon));
309+ }
310+
311+ /* The function for grabbing a menu from the module
312+ execute it, and make sure everything is a-okay */
313+ get_menu_t lget_menu = NULL;
314+ if (!g_module_symbol(module, INDICATOR_GET_MENU_S, (gpointer *)(&lget_menu))) {
315+ g_warning("Unable to get '" INDICATOR_GET_MENU_S "' symbol from module: %s", file);
316+ goto unrefandout;
317+ }
318+ if (lget_menu == NULL) {
319+ g_warning("Symbol '" INDICATOR_GET_MENU_S "' is (null) in module: %s", file);
320+ goto unrefandout;
321+ }
322+ priv->menu = lget_menu();
323+ if (priv->menu) {
324+ g_object_ref(G_OBJECT(priv->menu));
325+ }
326+
327+ if (priv->label == NULL && priv->icon == NULL) {
328+ /* This is the case where there is nothing to display,
329+ kinda odd that we'd have a module with nothing. */
330+ g_warning("No label or icon. Odd.");
331+ goto unrefandout;
332+ }
333+
334+ return INDICATOR_OBJECT(object);
335+
336+ /* Error, let's drop the object and return NULL. Sad when
337+ this happens. */
338+unrefandout:
339+ g_object_unref(object);
340+ return NULL;
341+}
342+
343+/**
344+ indicator_object_get_label:
345+ @io: An #IndicatorObject.
346+
347+ A function to get the label for a particular object. This
348+ function does not increase the refcount. That's your job
349+ if you want to do it.
350+
351+ Return value: A #GtkLabel or #NULL if unavailable.
352+*/
353+GtkLabel *
354+indicator_object_get_label (IndicatorObject * io)
355+{
356+ g_return_val_if_fail(IS_INDICATOR_OBJECT(io), NULL);
357+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io);
358+ return priv->label;
359+}
360+
361+/**
362+ indicator_object_get_icon:
363+ @io: An #IndicatorObject.
364+
365+ A function to get the icon for a particular object. This
366+ function does not increase the refcount. That's your job
367+ if you want to do it.
368+
369+ Return value: A #GtkImage or #NULL if unavailable.
370+*/
371+GtkImage *
372+indicator_object_get_icon (IndicatorObject * io)
373+{
374+ g_return_val_if_fail(IS_INDICATOR_OBJECT(io), NULL);
375+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io);
376+ return priv->icon;
377+}
378+
379+/**
380+ indicator_object_get_menu:
381+ @io: An #IndicatorObject.
382+
383+ A function to get the menu for a particular object. This
384+ function does not increase the refcount. That's your job
385+ if you want to do it.
386+
387+ Return value: A #GtkMenu or #NULL if unavailable.
388+*/
389+GtkMenu *
390+indicator_object_get_menu (IndicatorObject * io)
391+{
392+ g_return_val_if_fail(IS_INDICATOR_OBJECT(io), NULL);
393+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io);
394+ return priv->menu;
395+}
396
397=== added file 'libindicator/indicator-object.h'
398--- libindicator/indicator-object.h 1970-01-01 00:00:00 +0000
399+++ libindicator/indicator-object.h 2009-11-03 23:08:11 +0000
400@@ -0,0 +1,61 @@
401+/*
402+An object to represent loadable indicator modules to make loading
403+them easy and objectified.
404+
405+Copyright 2009 Canonical Ltd.
406+
407+Authors:
408+ Ted Gould <ted@canonical.com>
409+
410+This library is free software; you can redistribute it and/or
411+modify it under the terms of the GNU General Public License
412+version 3.0 as published by the Free Software Foundation.
413+
414+This library is distributed in the hope that it will be useful,
415+but WITHOUT ANY WARRANTY; without even the implied warranty of
416+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
417+GNU General Public License version 3.0 for more details.
418+
419+You should have received a copy of the GNU General Public
420+License along with this library. If not, see
421+<http://www.gnu.org/licenses/>.
422+*/
423+
424+#ifndef __INDICATOR_OBJECT_H__
425+#define __INDICATOR_OBJECT_H__
426+
427+#include <glib.h>
428+#include <glib-object.h>
429+
430+G_BEGIN_DECLS
431+
432+#define INDICATOR_OBJECT_TYPE (indicator_object_get_type ())
433+#define INDICATOR_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_OBJECT_TYPE, IndicatorObject))
434+#define INDICATOR_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_OBJECT_TYPE, IndicatorObjectClass))
435+#define IS_INDICATOR_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_OBJECT_TYPE))
436+#define IS_INDICATOR_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_OBJECT_TYPE))
437+#define INDICATOR_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_OBJECT_TYPE, IndicatorObjectClass))
438+
439+typedef struct _IndicatorObject IndicatorObject;
440+typedef struct _IndicatorObjectClass IndicatorObjectClass;
441+
442+struct _IndicatorObjectClass {
443+ GObjectClass parent_class;
444+
445+};
446+
447+struct _IndicatorObject {
448+ GObject parent;
449+
450+};
451+
452+GType indicator_object_get_type (void);
453+IndicatorObject * indicator_object_new_from_file (const gchar * file);
454+
455+GtkLabel * indicator_object_get_label (IndicatorObject * io);
456+GtkImage * indicator_object_get_icon (IndicatorObject * io);
457+GtkMenu * indicator_object_get_menu (IndicatorObject * io);
458+
459+G_END_DECLS
460+
461+#endif
462
463=== added directory 'tests'
464=== added file 'tests/Makefile.am'
465--- tests/Makefile.am 1970-01-01 00:00:00 +0000
466+++ tests/Makefile.am 2009-11-03 23:08:11 +0000
467@@ -0,0 +1,92 @@
468+
469+check_PROGRAMS = \
470+ test-loader
471+
472+lib_LTLIBRARIES = \
473+ libdummy-indicator-blank.la \
474+ libdummy-indicator-null.la \
475+ libdummy-indicator-simple.la
476+
477+#############################
478+# Test Loader
479+#############################
480+
481+test_loader_SOURCES = \
482+ test-loader.c
483+
484+test_loader_CFLAGS = \
485+ -Wall -Werror \
486+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir) \
487+ -DBUILD_DIR="\"$(builddir)\""
488+
489+test_loader_LDADD = \
490+ $(LIBINDICATOR_LIBS) $(top_builddir)/libindicator/.libs/libindicator.a
491+
492+#############################
493+# Dummy Indicator Blank
494+#############################
495+
496+libdummy_indicator_blank_la_SOURCES = \
497+ dummy-indicator-blank.c
498+
499+libdummy_indicator_blank_la_CFLAGS = \
500+ -Wall -Werror \
501+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
502+
503+libdummy_indicator_blank_la_LIBADD = \
504+ $(LIBINDICATOR_LIBS)
505+
506+libdummy_indicator_blank_la_LDFLAGS = \
507+ -module \
508+ -avoid-version
509+
510+#############################
511+# Dummy Indicator NULL
512+#############################
513+
514+libdummy_indicator_null_la_SOURCES = \
515+ dummy-indicator-null.c
516+
517+libdummy_indicator_null_la_CFLAGS = \
518+ -Wall -Werror \
519+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
520+
521+libdummy_indicator_null_la_LIBADD = \
522+ $(LIBINDICATOR_LIBS)
523+
524+libdummy_indicator_null_la_LDFLAGS = \
525+ -module \
526+ -avoid-version
527+
528+#############################
529+# Dummy Indicator Simple
530+#############################
531+
532+libdummy_indicator_simple_la_SOURCES = \
533+ dummy-indicator-simple.c
534+
535+libdummy_indicator_simple_la_CFLAGS = \
536+ -Wall -Werror \
537+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
538+
539+libdummy_indicator_simple_la_LIBADD = \
540+ $(LIBINDICATOR_LIBS)
541+
542+libdummy_indicator_simple_la_LDFLAGS = \
543+ -module \
544+ -avoid-version
545+
546+#############################
547+# Test stuff
548+#############################
549+
550+XML_REPORT = loader-check-results.xml
551+HTML_REPORT = loader-check-results.html
552+
553+loader-tester: test-loader libdummy-indicator-null.la libdummy-indicator-simple.la
554+ @gtester -k --verbose -o=$(XML_REPORT) ./test-loader
555+
556+check-local: loader-tester
557+
558+DISTCLEANFILES = $(XML_REPORT) $(HTML_REPORT)
559+
560
561=== added file 'tests/dummy-indicator-blank.c'
562--- tests/dummy-indicator-blank.c 1970-01-01 00:00:00 +0000
563+++ tests/dummy-indicator-blank.c 2009-11-03 23:08:11 +0000
564@@ -0,0 +1,6 @@
565+
566+#include "libindicator/indicator.h"
567+
568+INDICATOR_SET_VERSION
569+INDICATOR_SET_NAME("dummy-indicator-null")
570+
571
572=== added file 'tests/dummy-indicator-null.c'
573--- tests/dummy-indicator-null.c 1970-01-01 00:00:00 +0000
574+++ tests/dummy-indicator-null.c 2009-11-03 23:08:11 +0000
575@@ -0,0 +1,23 @@
576+
577+#include "libindicator/indicator.h"
578+
579+INDICATOR_SET_VERSION
580+INDICATOR_SET_NAME("dummy-indicator-null")
581+
582+GtkLabel *
583+get_label (void)
584+{
585+ return NULL;
586+}
587+
588+GtkImage *
589+get_icon (void)
590+{
591+ return NULL;
592+}
593+
594+GtkMenu *
595+get_menu (void)
596+{
597+ return NULL;
598+}
599
600=== added file 'tests/dummy-indicator-simple.c'
601--- tests/dummy-indicator-simple.c 1970-01-01 00:00:00 +0000
602+++ tests/dummy-indicator-simple.c 2009-11-03 23:08:11 +0000
603@@ -0,0 +1,28 @@
604+
605+#include "libindicator/indicator.h"
606+
607+INDICATOR_SET_VERSION
608+INDICATOR_SET_NAME("dummy-indicator-simple")
609+
610+GtkLabel *
611+get_label (void)
612+{
613+ return GTK_LABEL(gtk_label_new("Simple Item"));
614+}
615+
616+GtkImage *
617+get_icon (void)
618+{
619+ return GTK_IMAGE(gtk_image_new());
620+}
621+
622+GtkMenu *
623+get_menu (void)
624+{
625+ GtkMenu * main_menu = GTK_MENU(gtk_menu_new());
626+ GtkWidget * loading_item = gtk_menu_item_new_with_label("Loading...");
627+ gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), loading_item);
628+ gtk_widget_show(GTK_WIDGET(loading_item));
629+
630+ return main_menu;
631+}
632
633=== added file 'tests/test-loader.c'
634--- tests/test-loader.c 1970-01-01 00:00:00 +0000
635+++ tests/test-loader.c 2009-11-03 23:08:11 +0000
636@@ -0,0 +1,109 @@
637+#include <gtk/gtk.h>
638+#include "libindicator/indicator-object.h"
639+
640+void destroy_cb (gpointer data, GObject * object);
641+
642+void
643+test_loader_filename_dummy_simple_accessors (void)
644+{
645+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so");
646+ g_assert(object != NULL);
647+
648+ g_assert(indicator_object_get_label(object) != NULL);
649+ g_assert(indicator_object_get_menu(object) != NULL);
650+ g_assert(indicator_object_get_icon(object) != NULL);
651+
652+ g_object_unref(object);
653+
654+ return;
655+}
656+
657+void
658+test_loader_filename_dummy_simple (void)
659+{
660+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so");
661+ g_assert(object != NULL);
662+
663+ gboolean unreffed = FALSE;
664+ g_object_weak_ref(G_OBJECT(object), destroy_cb, &unreffed);
665+
666+ g_object_unref(object);
667+ g_assert(unreffed == TRUE);
668+
669+ return;
670+}
671+
672+void
673+test_loader_filename_dummy_blank (void)
674+{
675+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-blank.so");
676+ g_assert(object == NULL);
677+ return;
678+}
679+
680+void
681+test_loader_filename_dummy_null (void)
682+{
683+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-null.so");
684+ g_assert(object == NULL);
685+ return;
686+}
687+
688+void
689+test_loader_filename_bad (void)
690+{
691+ IndicatorObject * object = indicator_object_new_from_file("/this/file/should/not/exist.so");
692+ g_assert(object == NULL);
693+ return;
694+}
695+
696+void
697+destroy_cb (gpointer data, GObject * object)
698+{
699+ gboolean * bob = (gboolean *)data;
700+ *bob = TRUE;
701+ return;
702+}
703+
704+void
705+test_loader_refunref (void)
706+{
707+ GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL);
708+
709+ gboolean unreffed = FALSE;
710+ g_object_weak_ref(object, destroy_cb, &unreffed);
711+
712+ g_object_unref(object);
713+
714+ g_assert(unreffed == TRUE);
715+
716+ return;
717+}
718+
719+void
720+test_loader_creation_deletion_suite (void)
721+{
722+ g_test_add_func ("/libindicator/loader/ref_and_unref", test_loader_refunref);
723+ g_test_add_func ("/libindicator/loader/filename_bad", test_loader_filename_bad);
724+ g_test_add_func ("/libindicator/loader/dummy/null_load", test_loader_filename_dummy_null);
725+ g_test_add_func ("/libindicator/loader/dummy/blank_load", test_loader_filename_dummy_null);
726+ g_test_add_func ("/libindicator/loader/dummy/simple_load", test_loader_filename_dummy_simple);
727+ g_test_add_func ("/libindicator/loader/dummy/simple_accessors", test_loader_filename_dummy_simple_accessors);
728+
729+ return;
730+}
731+
732+
733+int
734+main (int argc, char ** argv)
735+{
736+ g_type_init ();
737+ g_test_init (&argc, &argv, NULL);
738+ gtk_init(&argc, &argv);
739+
740+ test_loader_creation_deletion_suite();
741+
742+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
743+
744+ return g_test_run();
745+}
746
747=== added directory 'tools'
748=== added file 'tools/Makefile.am'
749--- tools/Makefile.am 1970-01-01 00:00:00 +0000
750+++ tools/Makefile.am 2009-11-03 23:08:11 +0000
751@@ -0,0 +1,1 @@
752+#Something

Subscribers

People subscribed via source and target branches