Merge lp:~ted/libappindicator/remove-service into lp:libappindicator

Proposed by Ted Gould
Status: Merged
Merged at revision: 170
Proposed branch: lp:~ted/libappindicator/remove-service
Merge into: lp:libappindicator
Diff against target: 4202 lines (+44/-3848)
21 files modified
COPYING (+0/-674)
Makefile.am (+2/-3)
autogen.sh (+1/-1)
configure.ac (+15/-53)
data/Makefile.am (+0/-17)
data/indicator-application.service.in (+0/-3)
data/ordering-override.keyfile (+0/-5)
docs/reference/Makefile.am (+2/-2)
example/Makefile.am (+2/-2)
src/Makefile.am (+5/-55)
src/application-service-appstore.c (+0/-1305)
src/application-service-appstore.h (+0/-73)
src/application-service-watcher.c (+0/-302)
src/application-service-watcher.h (+0/-61)
src/application-service.c (+0/-78)
src/application-service.xml (+0/-59)
src/dbus-properties.xml (+0/-23)
src/indicator-application.c (+0/-879)
src/notification-approver.xml (+0/-29)
tests/Makefile.am (+17/-45)
tests/test-approver.c (+0/-179)
To merge this branch: bzr merge lp:~ted/libappindicator/remove-service
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+42561@code.launchpad.net

Description of the change

Remove the service from the repo so that it's lib only.

To post a comment you must log in.
179. By Ted Gould

Updating to trunk so that we get the GI fixes

180. By Ted Gould

Updating to trunk with GTK3 support.

181. By Ted Gould

Merging from trunk with the desktop convience function.

182. By Ted Gould

No indicator directory without the service

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== removed file 'COPYING'
--- COPYING 2009-11-30 21:22:03 +0000
+++ COPYING 1970-01-01 00:00:00 +0000
@@ -1,674 +0,0 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU General Public License is a free, copyleft license for
11software and other kinds of works.
12
13 The licenses for most software and other practical works are designed
14to take away your freedom to share and change the works. By contrast,
15the GNU General Public License is intended to guarantee your freedom to
16share and change all versions of a program--to make sure it remains free
17software for all its users. We, the Free Software Foundation, use the
18GNU General Public License for most of our software; it applies also to
19any other work released this way by its authors. You can apply it to
20your programs, too.
21
22 When we speak of free software, we are referring to freedom, not
23price. Our General Public Licenses are designed to make sure that you
24have the freedom to distribute copies of free software (and charge for
25them if you wish), that you receive source code or can get it if you
26want it, that you can change the software or use pieces of it in new
27free programs, and that you know you can do these things.
28
29 To protect your rights, we need to prevent others from denying you
30these rights or asking you to surrender the rights. Therefore, you have
31certain responsibilities if you distribute copies of the software, or if
32you modify it: responsibilities to respect the freedom of others.
33
34 For example, if you distribute copies of such a program, whether
35gratis or for a fee, you must pass on to the recipients the same
36freedoms that you received. You must make sure that they, too, receive
37or can get the source code. And you must show them these terms so they
38know their rights.
39
40 Developers that use the GNU GPL protect your rights with two steps:
41(1) assert copyright on the software, and (2) offer you this License
42giving you legal permission to copy, distribute and/or modify it.
43
44 For the developers' and authors' protection, the GPL clearly explains
45that there is no warranty for this free software. For both users' and
46authors' sake, the GPL requires that modified versions be marked as
47changed, so that their problems will not be attributed erroneously to
48authors of previous versions.
49
50 Some devices are designed to deny users access to install or run
51modified versions of the software inside them, although the manufacturer
52can do so. This is fundamentally incompatible with the aim of
53protecting users' freedom to change the software. The systematic
54pattern of such abuse occurs in the area of products for individuals to
55use, which is precisely where it is most unacceptable. Therefore, we
56have designed this version of the GPL to prohibit the practice for those
57products. If such problems arise substantially in other domains, we
58stand ready to extend this provision to those domains in future versions
59of the GPL, as needed to protect the freedom of users.
60
61 Finally, every program is threatened constantly by software patents.
62States should not allow patents to restrict development and use of
63software on general-purpose computers, but in those that do, we wish to
64avoid the special danger that patents applied to a free program could
65make it effectively proprietary. To prevent this, the GPL assures that
66patents cannot be used to render the program non-free.
67
68 The precise terms and conditions for copying, distribution and
69modification follow.
70
71 TERMS AND CONDITIONS
72
73 0. Definitions.
74
75 "This License" refers to version 3 of the GNU General Public License.
76
77 "Copyright" also means copyright-like laws that apply to other kinds of
78works, such as semiconductor masks.
79
80 "The Program" refers to any copyrightable work licensed under this
81License. Each licensee is addressed as "you". "Licensees" and
82"recipients" may be individuals or organizations.
83
84 To "modify" a work means to copy from or adapt all or part of the work
85in a fashion requiring copyright permission, other than the making of an
86exact copy. The resulting work is called a "modified version" of the
87earlier work or a work "based on" the earlier work.
88
89 A "covered work" means either the unmodified Program or a work based
90on the Program.
91
92 To "propagate" a work means to do anything with it that, without
93permission, would make you directly or secondarily liable for
94infringement under applicable copyright law, except executing it on a
95computer or modifying a private copy. Propagation includes copying,
96distribution (with or without modification), making available to the
97public, and in some countries other activities as well.
98
99 To "convey" a work means any kind of propagation that enables other
100parties to make or receive copies. Mere interaction with a user through
101a computer network, with no transfer of a copy, is not conveying.
102
103 An interactive user interface displays "Appropriate Legal Notices"
104to the extent that it includes a convenient and prominently visible
105feature that (1) displays an appropriate copyright notice, and (2)
106tells the user that there is no warranty for the work (except to the
107extent that warranties are provided), that licensees may convey the
108work under this License, and how to view a copy of this License. If
109the interface presents a list of user commands or options, such as a
110menu, a prominent item in the list meets this criterion.
111
112 1. Source Code.
113
114 The "source code" for a work means the preferred form of the work
115for making modifications to it. "Object code" means any non-source
116form of a work.
117
118 A "Standard Interface" means an interface that either is an official
119standard defined by a recognized standards body, or, in the case of
120interfaces specified for a particular programming language, one that
121is widely used among developers working in that language.
122
123 The "System Libraries" of an executable work include anything, other
124than the work as a whole, that (a) is included in the normal form of
125packaging a Major Component, but which is not part of that Major
126Component, and (b) serves only to enable use of the work with that
127Major Component, or to implement a Standard Interface for which an
128implementation is available to the public in source code form. A
129"Major Component", in this context, means a major essential component
130(kernel, window system, and so on) of the specific operating system
131(if any) on which the executable work runs, or a compiler used to
132produce the work, or an object code interpreter used to run it.
133
134 The "Corresponding Source" for a work in object code form means all
135the source code needed to generate, install, and (for an executable
136work) run the object code and to modify the work, including scripts to
137control those activities. However, it does not include the work's
138System Libraries, or general-purpose tools or generally available free
139programs which are used unmodified in performing those activities but
140which are not part of the work. For example, Corresponding Source
141includes interface definition files associated with source files for
142the work, and the source code for shared libraries and dynamically
143linked subprograms that the work is specifically designed to require,
144such as by intimate data communication or control flow between those
145subprograms and other parts of the work.
146
147 The Corresponding Source need not include anything that users
148can regenerate automatically from other parts of the Corresponding
149Source.
150
151 The Corresponding Source for a work in source code form is that
152same work.
153
154 2. Basic Permissions.
155
156 All rights granted under this License are granted for the term of
157copyright on the Program, and are irrevocable provided the stated
158conditions are met. This License explicitly affirms your unlimited
159permission to run the unmodified Program. The output from running a
160covered work is covered by this License only if the output, given its
161content, constitutes a covered work. This License acknowledges your
162rights of fair use or other equivalent, as provided by copyright law.
163
164 You may make, run and propagate covered works that you do not
165convey, without conditions so long as your license otherwise remains
166in force. You may convey covered works to others for the sole purpose
167of having them make modifications exclusively for you, or provide you
168with facilities for running those works, provided that you comply with
169the terms of this License in conveying all material for which you do
170not control copyright. Those thus making or running the covered works
171for you must do so exclusively on your behalf, under your direction
172and control, on terms that prohibit them from making any copies of
173your copyrighted material outside their relationship with you.
174
175 Conveying under any other circumstances is permitted solely under
176the conditions stated below. Sublicensing is not allowed; section 10
177makes it unnecessary.
178
179 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
181 No covered work shall be deemed part of an effective technological
182measure under any applicable law fulfilling obligations under article
18311 of the WIPO copyright treaty adopted on 20 December 1996, or
184similar laws prohibiting or restricting circumvention of such
185measures.
186
187 When you convey a covered work, you waive any legal power to forbid
188circumvention of technological measures to the extent such circumvention
189is effected by exercising rights under this License with respect to
190the covered work, and you disclaim any intention to limit operation or
191modification of the work as a means of enforcing, against the work's
192users, your or third parties' legal rights to forbid circumvention of
193technological measures.
194
195 4. Conveying Verbatim Copies.
196
197 You may convey verbatim copies of the Program's source code as you
198receive it, in any medium, provided that you conspicuously and
199appropriately publish on each copy an appropriate copyright notice;
200keep intact all notices stating that this License and any
201non-permissive terms added in accord with section 7 apply to the code;
202keep intact all notices of the absence of any warranty; and give all
203recipients a copy of this License along with the Program.
204
205 You may charge any price or no price for each copy that you convey,
206and you may offer support or warranty protection for a fee.
207
208 5. Conveying Modified Source Versions.
209
210 You may convey a work based on the Program, or the modifications to
211produce it from the Program, in the form of source code under the
212terms of section 4, provided that you also meet all of these conditions:
213
214 a) The work must carry prominent notices stating that you modified
215 it, and giving a relevant date.
216
217 b) The work must carry prominent notices stating that it is
218 released under this License and any conditions added under section
219 7. This requirement modifies the requirement in section 4 to
220 "keep intact all notices".
221
222 c) You must license the entire work, as a whole, under this
223 License to anyone who comes into possession of a copy. This
224 License will therefore apply, along with any applicable section 7
225 additional terms, to the whole of the work, and all its parts,
226 regardless of how they are packaged. This License gives no
227 permission to license the work in any other way, but it does not
228 invalidate such permission if you have separately received it.
229
230 d) If the work has interactive user interfaces, each must display
231 Appropriate Legal Notices; however, if the Program has interactive
232 interfaces that do not display Appropriate Legal Notices, your
233 work need not make them do so.
234
235 A compilation of a covered work with other separate and independent
236works, which are not by their nature extensions of the covered work,
237and which are not combined with it such as to form a larger program,
238in or on a volume of a storage or distribution medium, is called an
239"aggregate" if the compilation and its resulting copyright are not
240used to limit the access or legal rights of the compilation's users
241beyond what the individual works permit. Inclusion of a covered work
242in an aggregate does not cause this License to apply to the other
243parts of the aggregate.
244
245 6. Conveying Non-Source Forms.
246
247 You may convey a covered work in object code form under the terms
248of sections 4 and 5, provided that you also convey the
249machine-readable Corresponding Source under the terms of this License,
250in one of these ways:
251
252 a) Convey the object code in, or embodied in, a physical product
253 (including a physical distribution medium), accompanied by the
254 Corresponding Source fixed on a durable physical medium
255 customarily used for software interchange.
256
257 b) Convey the object code in, or embodied in, a physical product
258 (including a physical distribution medium), accompanied by a
259 written offer, valid for at least three years and valid for as
260 long as you offer spare parts or customer support for that product
261 model, to give anyone who possesses the object code either (1) a
262 copy of the Corresponding Source for all the software in the
263 product that is covered by this License, on a durable physical
264 medium customarily used for software interchange, for a price no
265 more than your reasonable cost of physically performing this
266 conveying of source, or (2) access to copy the
267 Corresponding Source from a network server at no charge.
268
269 c) Convey individual copies of the object code with a copy of the
270 written offer to provide the Corresponding Source. This
271 alternative is allowed only occasionally and noncommercially, and
272 only if you received the object code with such an offer, in accord
273 with subsection 6b.
274
275 d) Convey the object code by offering access from a designated
276 place (gratis or for a charge), and offer equivalent access to the
277 Corresponding Source in the same way through the same place at no
278 further charge. You need not require recipients to copy the
279 Corresponding Source along with the object code. If the place to
280 copy the object code is a network server, the Corresponding Source
281 may be on a different server (operated by you or a third party)
282 that supports equivalent copying facilities, provided you maintain
283 clear directions next to the object code saying where to find the
284 Corresponding Source. Regardless of what server hosts the
285 Corresponding Source, you remain obligated to ensure that it is
286 available for as long as needed to satisfy these requirements.
287
288 e) Convey the object code using peer-to-peer transmission, provided
289 you inform other peers where the object code and Corresponding
290 Source of the work are being offered to the general public at no
291 charge under subsection 6d.
292
293 A separable portion of the object code, whose source code is excluded
294from the Corresponding Source as a System Library, need not be
295included in conveying the object code work.
296
297 A "User Product" is either (1) a "consumer product", which means any
298tangible personal property which is normally used for personal, family,
299or household purposes, or (2) anything designed or sold for incorporation
300into a dwelling. In determining whether a product is a consumer product,
301doubtful cases shall be resolved in favor of coverage. For a particular
302product received by a particular user, "normally used" refers to a
303typical or common use of that class of product, regardless of the status
304of the particular user or of the way in which the particular user
305actually uses, or expects or is expected to use, the product. A product
306is a consumer product regardless of whether the product has substantial
307commercial, industrial or non-consumer uses, unless such uses represent
308the only significant mode of use of the product.
309
310 "Installation Information" for a User Product means any methods,
311procedures, authorization keys, or other information required to install
312and execute modified versions of a covered work in that User Product from
313a modified version of its Corresponding Source. The information must
314suffice to ensure that the continued functioning of the modified object
315code is in no case prevented or interfered with solely because
316modification has been made.
317
318 If you convey an object code work under this section in, or with, or
319specifically for use in, a User Product, and the conveying occurs as
320part of a transaction in which the right of possession and use of the
321User Product is transferred to the recipient in perpetuity or for a
322fixed term (regardless of how the transaction is characterized), the
323Corresponding Source conveyed under this section must be accompanied
324by the Installation Information. But this requirement does not apply
325if neither you nor any third party retains the ability to install
326modified object code on the User Product (for example, the work has
327been installed in ROM).
328
329 The requirement to provide Installation Information does not include a
330requirement to continue to provide support service, warranty, or updates
331for a work that has been modified or installed by the recipient, or for
332the User Product in which it has been modified or installed. Access to a
333network may be denied when the modification itself materially and
334adversely affects the operation of the network or violates the rules and
335protocols for communication across the network.
336
337 Corresponding Source conveyed, and Installation Information provided,
338in accord with this section must be in a format that is publicly
339documented (and with an implementation available to the public in
340source code form), and must require no special password or key for
341unpacking, reading or copying.
342
343 7. Additional Terms.
344
345 "Additional permissions" are terms that supplement the terms of this
346License by making exceptions from one or more of its conditions.
347Additional permissions that are applicable to the entire Program shall
348be treated as though they were included in this License, to the extent
349that they are valid under applicable law. If additional permissions
350apply only to part of the Program, that part may be used separately
351under those permissions, but the entire Program remains governed by
352this License without regard to the additional permissions.
353
354 When you convey a copy of a covered work, you may at your option
355remove any additional permissions from that copy, or from any part of
356it. (Additional permissions may be written to require their own
357removal in certain cases when you modify the work.) You may place
358additional permissions on material, added by you to a covered work,
359for which you have or can give appropriate copyright permission.
360
361 Notwithstanding any other provision of this License, for material you
362add to a covered work, you may (if authorized by the copyright holders of
363that material) supplement the terms of this License with terms:
364
365 a) Disclaiming warranty or limiting liability differently from the
366 terms of sections 15 and 16 of this License; or
367
368 b) Requiring preservation of specified reasonable legal notices or
369 author attributions in that material or in the Appropriate Legal
370 Notices displayed by works containing it; or
371
372 c) Prohibiting misrepresentation of the origin of that material, or
373 requiring that modified versions of such material be marked in
374 reasonable ways as different from the original version; or
375
376 d) Limiting the use for publicity purposes of names of licensors or
377 authors of the material; or
378
379 e) Declining to grant rights under trademark law for use of some
380 trade names, trademarks, or service marks; or
381
382 f) Requiring indemnification of licensors and authors of that
383 material by anyone who conveys the material (or modified versions of
384 it) with contractual assumptions of liability to the recipient, for
385 any liability that these contractual assumptions directly impose on
386 those licensors and authors.
387
388 All other non-permissive additional terms are considered "further
389restrictions" within the meaning of section 10. If the Program as you
390received it, or any part of it, contains a notice stating that it is
391governed by this License along with a term that is a further
392restriction, you may remove that term. If a license document contains
393a further restriction but permits relicensing or conveying under this
394License, you may add to a covered work material governed by the terms
395of that license document, provided that the further restriction does
396not survive such relicensing or conveying.
397
398 If you add terms to a covered work in accord with this section, you
399must place, in the relevant source files, a statement of the
400additional terms that apply to those files, or a notice indicating
401where to find the applicable terms.
402
403 Additional terms, permissive or non-permissive, may be stated in the
404form of a separately written license, or stated as exceptions;
405the above requirements apply either way.
406
407 8. Termination.
408
409 You may not propagate or modify a covered work except as expressly
410provided under this License. Any attempt otherwise to propagate or
411modify it is void, and will automatically terminate your rights under
412this License (including any patent licenses granted under the third
413paragraph of section 11).
414
415 However, if you cease all violation of this License, then your
416license from a particular copyright holder is reinstated (a)
417provisionally, unless and until the copyright holder explicitly and
418finally terminates your license, and (b) permanently, if the copyright
419holder fails to notify you of the violation by some reasonable means
420prior to 60 days after the cessation.
421
422 Moreover, your license from a particular copyright holder is
423reinstated permanently if the copyright holder notifies you of the
424violation by some reasonable means, this is the first time you have
425received notice of violation of this License (for any work) from that
426copyright holder, and you cure the violation prior to 30 days after
427your receipt of the notice.
428
429 Termination of your rights under this section does not terminate the
430licenses of parties who have received copies or rights from you under
431this License. If your rights have been terminated and not permanently
432reinstated, you do not qualify to receive new licenses for the same
433material under section 10.
434
435 9. Acceptance Not Required for Having Copies.
436
437 You are not required to accept this License in order to receive or
438run a copy of the Program. Ancillary propagation of a covered work
439occurring solely as a consequence of using peer-to-peer transmission
440to receive a copy likewise does not require acceptance. However,
441nothing other than this License grants you permission to propagate or
442modify any covered work. These actions infringe copyright if you do
443not accept this License. Therefore, by modifying or propagating a
444covered work, you indicate your acceptance of this License to do so.
445
446 10. Automatic Licensing of Downstream Recipients.
447
448 Each time you convey a covered work, the recipient automatically
449receives a license from the original licensors, to run, modify and
450propagate that work, subject to this License. You are not responsible
451for enforcing compliance by third parties with this License.
452
453 An "entity transaction" is a transaction transferring control of an
454organization, or substantially all assets of one, or subdividing an
455organization, or merging organizations. If propagation of a covered
456work results from an entity transaction, each party to that
457transaction who receives a copy of the work also receives whatever
458licenses to the work the party's predecessor in interest had or could
459give under the previous paragraph, plus a right to possession of the
460Corresponding Source of the work from the predecessor in interest, if
461the predecessor has it or can get it with reasonable efforts.
462
463 You may not impose any further restrictions on the exercise of the
464rights granted or affirmed under this License. For example, you may
465not impose a license fee, royalty, or other charge for exercise of
466rights granted under this License, and you may not initiate litigation
467(including a cross-claim or counterclaim in a lawsuit) alleging that
468any patent claim is infringed by making, using, selling, offering for
469sale, or importing the Program or any portion of it.
470
471 11. Patents.
472
473 A "contributor" is a copyright holder who authorizes use under this
474License of the Program or a work on which the Program is based. The
475work thus licensed is called the contributor's "contributor version".
476
477 A contributor's "essential patent claims" are all patent claims
478owned or controlled by the contributor, whether already acquired or
479hereafter acquired, that would be infringed by some manner, permitted
480by this License, of making, using, or selling its contributor version,
481but do not include claims that would be infringed only as a
482consequence of further modification of the contributor version. For
483purposes of this definition, "control" includes the right to grant
484patent sublicenses in a manner consistent with the requirements of
485this License.
486
487 Each contributor grants you a non-exclusive, worldwide, royalty-free
488patent license under the contributor's essential patent claims, to
489make, use, sell, offer for sale, import and otherwise run, modify and
490propagate the contents of its contributor version.
491
492 In the following three paragraphs, a "patent license" is any express
493agreement or commitment, however denominated, not to enforce a patent
494(such as an express permission to practice a patent or covenant not to
495sue for patent infringement). To "grant" such a patent license to a
496party means to make such an agreement or commitment not to enforce a
497patent against the party.
498
499 If you convey a covered work, knowingly relying on a patent license,
500and the Corresponding Source of the work is not available for anyone
501to copy, free of charge and under the terms of this License, through a
502publicly available network server or other readily accessible means,
503then you must either (1) cause the Corresponding Source to be so
504available, or (2) arrange to deprive yourself of the benefit of the
505patent license for this particular work, or (3) arrange, in a manner
506consistent with the requirements of this License, to extend the patent
507license to downstream recipients. "Knowingly relying" means you have
508actual knowledge that, but for the patent license, your conveying the
509covered work in a country, or your recipient's use of the covered work
510in a country, would infringe one or more identifiable patents in that
511country that you have reason to believe are valid.
512
513 If, pursuant to or in connection with a single transaction or
514arrangement, you convey, or propagate by procuring conveyance of, a
515covered work, and grant a patent license to some of the parties
516receiving the covered work authorizing them to use, propagate, modify
517or convey a specific copy of the covered work, then the patent license
518you grant is automatically extended to all recipients of the covered
519work and works based on it.
520
521 A patent license is "discriminatory" if it does not include within
522the scope of its coverage, prohibits the exercise of, or is
523conditioned on the non-exercise of one or more of the rights that are
524specifically granted under this License. You may not convey a covered
525work if you are a party to an arrangement with a third party that is
526in the business of distributing software, under which you make payment
527to the third party based on the extent of your activity of conveying
528the work, and under which the third party grants, to any of the
529parties who would receive the covered work from you, a discriminatory
530patent license (a) in connection with copies of the covered work
531conveyed by you (or copies made from those copies), or (b) primarily
532for and in connection with specific products or compilations that
533contain the covered work, unless you entered into that arrangement,
534or that patent license was granted, prior to 28 March 2007.
535
536 Nothing in this License shall be construed as excluding or limiting
537any implied license or other defenses to infringement that may
538otherwise be available to you under applicable patent law.
539
540 12. No Surrender of Others' Freedom.
541
542 If conditions are imposed on you (whether by court order, agreement or
543otherwise) that contradict the conditions of this License, they do not
544excuse you from the conditions of this License. If you cannot convey a
545covered work so as to satisfy simultaneously your obligations under this
546License and any other pertinent obligations, then as a consequence you may
547not convey it at all. For example, if you agree to terms that obligate you
548to collect a royalty for further conveying from those to whom you convey
549the Program, the only way you could satisfy both those terms and this
550License would be to refrain entirely from conveying the Program.
551
552 13. Use with the GNU Affero General Public License.
553
554 Notwithstanding any other provision of this License, you have
555permission to link or combine any covered work with a work licensed
556under version 3 of the GNU Affero General Public License into a single
557combined work, and to convey the resulting work. The terms of this
558License will continue to apply to the part which is the covered work,
559but the special requirements of the GNU Affero General Public License,
560section 13, concerning interaction through a network will apply to the
561combination as such.
562
563 14. Revised Versions of this License.
564
565 The Free Software Foundation may publish revised and/or new versions of
566the GNU General Public License from time to time. Such new versions will
567be similar in spirit to the present version, but may differ in detail to
568address new problems or concerns.
569
570 Each version is given a distinguishing version number. If the
571Program specifies that a certain numbered version of the GNU General
572Public License "or any later version" applies to it, you have the
573option of following the terms and conditions either of that numbered
574version or of any later version published by the Free Software
575Foundation. If the Program does not specify a version number of the
576GNU General Public License, you may choose any version ever published
577by the Free Software Foundation.
578
579 If the Program specifies that a proxy can decide which future
580versions of the GNU General Public License can be used, that proxy's
581public statement of acceptance of a version permanently authorizes you
582to choose that version for the Program.
583
584 Later license versions may give you additional or different
585permissions. However, no additional obligations are imposed on any
586author or copyright holder as a result of your choosing to follow a
587later version.
588
589 15. Disclaimer of Warranty.
590
591 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
600 16. Limitation of Liability.
601
602 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610SUCH DAMAGES.
611
612 17. Interpretation of Sections 15 and 16.
613
614 If the disclaimer of warranty and limitation of liability provided
615above cannot be given local legal effect according to their terms,
616reviewing courts shall apply local law that most closely approximates
617an absolute waiver of all civil liability in connection with the
618Program, unless a warranty or assumption of liability accompanies a
619copy of the Program in return for a fee.
620
621 END OF TERMS AND CONDITIONS
622
623 How to Apply These Terms to Your New Programs
624
625 If you develop a new program, and you want it to be of the greatest
626possible use to the public, the best way to achieve this is to make it
627free software which everyone can redistribute and change under these terms.
628
629 To do so, attach the following notices to the program. It is safest
630to attach them to the start of each source file to most effectively
631state the exclusion of warranty; and each file should have at least
632the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
636
637 This program is free software: you can redistribute it and/or modify
638 it under the terms of the GNU General Public License as published by
639 the Free Software Foundation, either version 3 of the License, or
640 (at your option) any later version.
641
642 This program is distributed in the hope that it will be useful,
643 but WITHOUT ANY WARRANTY; without even the implied warranty of
644 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 GNU General Public License for more details.
646
647 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
649
650Also add information on how to contact you by electronic and paper mail.
651
652 If the program does terminal interaction, make it output a short
653notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
656 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 This is free software, and you are welcome to redistribute it
658 under certain conditions; type `show c' for details.
659
660The hypothetical commands `show w' and `show c' should show the appropriate
661parts of the General Public License. Of course, your program's commands
662might be different; for a GUI interface, you would use an "about box".
663
664 You should also get your employer (if you work as a programmer) or school,
665if any, to sign a "copyright disclaimer" for the program, if necessary.
666For more information on this, and how to apply and follow the GNU GPL, see
667<http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670into proprietary programs. If your program is a subroutine library, you
671may consider it more useful to permit linking proprietary applications with
672the library. If this is what you want to do, use the GNU Lesser General
673Public License instead of this License. But first, please read
674<http://www.gnu.org/philosophy/why-not-lgpl.html>.
6750
=== renamed file 'COPYING.LGPL.3' => 'COPYING'
=== modified file 'Makefile.am'
--- Makefile.am 2010-09-15 22:16:00 +0000
+++ Makefile.am 2010-12-06 15:12:11 +0000
@@ -1,5 +1,5 @@
1SUBDIRS = data \1SUBDIRS = \
2 src \2 src \
3 bindings \3 bindings \
4 example \4 example \
5 tests \5 tests \
@@ -12,7 +12,6 @@
12 xmldocs.make \12 xmldocs.make \
13 autogen.sh \13 autogen.sh \
14 COPYING.LGPL.2.1 \14 COPYING.LGPL.2.1 \
15 COPYING.LGPL.3 \
16 ChangeLog15 ChangeLog
1716
18DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-localinstall --enable-introspection17DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-localinstall --enable-introspection
1918
=== modified file 'autogen.sh'
--- autogen.sh 2009-12-09 20:25:32 +0000
+++ autogen.sh 2010-12-06 15:12:11 +0000
@@ -1,6 +1,6 @@
1#!/bin/sh1#!/bin/sh
22
3PKG_NAME="indicator-application"3PKG_NAME="liappindicator"
44
5which gnome-autogen.sh || {5which gnome-autogen.sh || {
6 echo "You need gnome-common from GNOME SVN"6 echo "You need gnome-common from GNOME SVN"
77
=== modified file 'configure.ac'
--- configure.ac 2010-12-04 03:43:40 +0000
+++ configure.ac 2010-12-06 15:12:11 +0000
@@ -1,11 +1,11 @@
11
2AC_INIT(indicator-application, 0.2.9, ted@canonical.com)2AC_INIT(libappindicator, 0.2.90, ted@canonical.com)
3AC_COPYRIGHT([Copyright 2009, 2010 Canonical])3AC_COPYRIGHT([Copyright 2009, 2010 Canonical])
44
5AC_PREREQ(2.53)5AC_PREREQ(2.53)
66
7AM_CONFIG_HEADER(config.h)7AM_CONFIG_HEADER(config.h)
8AM_INIT_AUTOMAKE(indicator-application, 0.2.9)8AM_INIT_AUTOMAKE(libappindicator, 0.2.90)
99
10AM_MAINTAINER_MODE10AM_MAINTAINER_MODE
1111
@@ -41,7 +41,6 @@
41GTK3_REQUIRED_VERSION=2.9141GTK3_REQUIRED_VERSION=2.91
42INDICATOR_REQUIRED_VERSION=0.3.542INDICATOR_REQUIRED_VERSION=0.3.5
43DBUSMENUGTK_REQUIRED_VERSION=0.2.243DBUSMENUGTK_REQUIRED_VERSION=0.2.2
44JSON_GLIB_REQUIRED_VERSION=0.7.6
45DBUS_GLIB_REQUIRED_VERSION=0.8244DBUS_GLIB_REQUIRED_VERSION=0.82
4645
47AC_ARG_WITH([gtk],46AC_ARG_WITH([gtk],
@@ -50,36 +49,26 @@
50 [],49 [],
51 [with_gtk=2])50 [with_gtk=2])
52AS_IF([test "x$with_gtk" = x3],51AS_IF([test "x$with_gtk" = x3],
53 [PKG_CHECK_MODULES(INDICATOR, gtk+-3.0 >= $GTK3_REQUIRED_VERSION52 [PKG_CHECK_MODULES(LIBRARAY, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
54 indicator3 >= $INDICATOR_REQUIRED_VERSION53 indicator3 >= $INDICATOR_REQUIRED_VERSION
55 json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION54 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
56 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION55 dbusmenu-gtk3 >= $DBUSMENUGTK_REQUIRED_VERSION)
57 dbusmenu-gtk3 >= $DBUSMENUGTK_REQUIRED_VERSION)56 AC_SUBST(LIBRARY_CFLAGS)
58 AC_SUBST(INDICATOR_CFLAGS)57 AC_SUBST(LIBRARY_LIBS)
59 AC_SUBST(INDICATOR_LIBS)
60 AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available])58 AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available])
61 ],59 ],
62 [test "x$with_gtk" = x2],60 [test "x$with_gtk" = x2],
63 [PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION61 [PKG_CHECK_MODULES(LIBRARY, gtk+-2.0 >= $GTK_REQUIRED_VERSION
64 indicator >= $INDICATOR_REQUIRED_VERSION 62 indicator >= $INDICATOR_REQUIRED_VERSION
65 json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION63 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
66 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION64 dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)
67 dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)65 AC_SUBST(LIBRARY_CFLAGS)
68 AC_SUBST(INDICATOR_CFLAGS)66 AC_SUBST(LIBRARY_LIBS)
69 AC_SUBST(INDICATOR_LIBS)
70 ],67 ],
71 [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]68 [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
72)69)
73AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3])70AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3])
7471
75PKG_CHECK_MODULES(LIBRARY, gtk+-2.0 >= $GTK_REQUIRED_VERSION
76 indicator >= $INDICATOR_REQUIRED_VERSION
77 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
78 dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION)
79
80AC_SUBST(LIBRARY_CFLAGS)
81AC_SUBST(LIBRARY_LIBS)
82
83###########################72###########################
84# GObject Introspection73# GObject Introspection
85###########################74###########################
@@ -164,31 +153,6 @@
164AC_ARG_ENABLE(localinstall, AS_HELP_STRING([--enable-localinstall], [install all of the files localy instead of system directories (for distcheck)]), with_localinstall=$enableval, with_localinstall=no)153AC_ARG_ENABLE(localinstall, AS_HELP_STRING([--enable-localinstall], [install all of the files localy instead of system directories (for distcheck)]), with_localinstall=$enableval, with_localinstall=no)
165154
166###########################155###########################
167# Indicator Info
168###########################
169
170if test "x$with_localinstall" = "xyes"; then
171 INDICATORDIR="${libdir}/indicators/2/"
172 INDICATORICONSDIR="${datadir}/libindicate/icons/"
173else
174 INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator`
175 INDICATORICONSDIR=`$PKG_CONFIG --variable=iconsdir indicator`
176fi
177AC_SUBST(INDICATORDIR)
178AC_SUBST(INDICATORICONSDIR)
179
180###########################
181# DBus Service Info
182###########################
183
184if test "x$with_localinstall" = "xyes"; then
185 DBUSSERVICEDIR="${datadir}/dbus-1/services/"
186else
187 DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`
188fi
189AC_SUBST(DBUSSERVICEDIR)
190
191###########################
192# Python156# Python
193###########################157###########################
194158
@@ -233,7 +197,6 @@
233bindings/mono/examples/Makefile197bindings/mono/examples/Makefile
234bindings/mono/examples/indicator-example198bindings/mono/examples/indicator-example
235bindings/python/Makefile199bindings/python/Makefile
236data/Makefile
237tests/Makefile200tests/Makefile
238example/Makefile201example/Makefile
239docs/Makefile202docs/Makefile
@@ -248,9 +211,8 @@
248211
249AC_MSG_NOTICE([212AC_MSG_NOTICE([
250213
251Application Indicator Configuration:214Libappindicator Configuration:
252215
253 Prefix: $prefix216 Prefix: $prefix
254 Indicator Dir: $INDICATORDIR
255 GTK+ Version: $with_gtk217 GTK+ Version: $with_gtk
256])218])
257219
=== removed directory 'data'
=== removed file 'data/Makefile.am'
--- data/Makefile.am 2010-08-10 21:31:39 +0000
+++ data/Makefile.am 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
1
2dbus_servicesdir = $(DBUSSERVICEDIR)
3dbus_services_DATA = indicator-application.service
4
5%.service: %.service.in
6 sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
7
8overridedir = $(pkgdatadir)
9override_DATA = ordering-override.keyfile
10
11EXTRA_DIST = \
12 indicator-application.service.in \
13 ordering-override.keyfile
14
15CLEANFILES = \
16 indicator-application.service
17
180
=== removed file 'data/indicator-application.service.in'
--- data/indicator-application.service.in 2009-11-25 03:52:40 +0000
+++ data/indicator-application.service.in 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
1[D-BUS Service]
2Name=org.ayatana.indicator.application
3Exec=@libexecdir@/indicator-application-service
40
=== removed file 'data/ordering-override.keyfile'
--- data/ordering-override.keyfile 2010-08-20 15:13:35 +0000
+++ data/ordering-override.keyfile 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
1[Ordering Index Overrides]
2gnome-power-manager=1
3gst-keyboard-xkb=2
4gsd-keyboard-xkb=3
5ibus=4
60
=== modified file 'docs/reference/Makefile.am'
--- docs/reference/Makefile.am 2010-12-03 22:15:12 +0000
+++ docs/reference/Makefile.am 2010-12-06 15:12:11 +0000
@@ -90,8 +90,8 @@
90# signals and properties.90# signals and properties.
91# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)91# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
92# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)92# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
93GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src $(INDICATOR_CFLAGS)93GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src $(LIBRARY_CFLAGS)
94GTKDOC_LIBS=$(top_builddir)/src/libappindicator.la $(top_builddir)/src/libapplication.la $(INDICATOR_LIBS)94GTKDOC_LIBS=$(top_builddir)/src/libappindicator.la $(LIBRARY_LIBS)
9595
96# This includes the standard gtk-doc make rules, copied by gtkdocize.96# This includes the standard gtk-doc make rules, copied by gtkdocize.
97include $(top_srcdir)/gtk-doc.local.make97include $(top_srcdir)/gtk-doc.local.make
9898
=== modified file 'example/Makefile.am'
--- example/Makefile.am 2009-11-30 19:12:49 +0000
+++ example/Makefile.am 2010-12-06 15:12:11 +0000
@@ -10,10 +10,10 @@
10 simple-client.c10 simple-client.c
1111
12simple_client_CFLAGS = \12simple_client_CFLAGS = \
13 $(INDICATOR_CFLAGS) \13 $(LIBRARY_CFLAGS) \
14 -Wall -Werror \14 -Wall -Werror \
15 -I$(top_srcdir)/src15 -I$(top_srcdir)/src
1616
17simple_client_LDADD = \17simple_client_LDADD = \
18 $(INDICATOR_LIBS) \18 $(LIBRARY_LIBS) \
19 $(top_builddir)/src/libappindicator.la19 $(top_builddir)/src/libappindicator.la
2020
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2010-12-04 03:43:40 +0000
+++ src/Makefile.am 2010-12-06 15:12:11 +0000
@@ -22,60 +22,12 @@
22include $(top_srcdir)/Makefile.am.marshal22include $(top_srcdir)/Makefile.am.marshal
2323
24##################################24##################################
25# Indicator25# Marshallers
26##################################26##################################
27
28applicationlibdir = $(INDICATORDIR)
29applicationlib_LTLIBRARIES = libapplication.la
30libapplication_la_SOURCES = \
31 application-service-marshal.c \
32 dbus-shared.h \
33 indicator-application.c
34libapplication_la_CFLAGS = $(INDICATOR_CFLAGS) \
35 -Wall \
36 -Wl,-Bsymbolic-functions \
37 -Wl,-z,defs \
38 -Wl,--as-needed \
39 -Werror \
40 -DG_LOG_DOMAIN=\"Indicator-Application\"
41libapplication_la_LIBADD = $(INDICATOR_LIBS)
42libapplication_la_LDFLAGS = -module -avoid-version
43
44##################################
45# Service
46##################################
47
48libexec_PROGRAMS = indicator-application-service
4927
50BUILT_SOURCES += \28BUILT_SOURCES += \
51 application-service-server.h \
52 application-service-marshal.h \29 application-service-marshal.h \
53 application-service-marshal.c \30 application-service-marshal.c
54 dbus-properties-client.h \
55 notification-item-client.h \
56 notification-watcher-server.h
57
58indicator_application_service_SOURCES = \
59 application-service.c \
60 application-service-appstore.h \
61 application-service-appstore.c \
62 application-service-marshal.c \
63 application-service-watcher.h \
64 application-service-watcher.c \
65 app-indicator-enum-types.c \
66 dbus-shared.h \
67 generate-id.h \
68 generate-id.c
69
70indicator_application_service_CFLAGS = \
71 $(INDICATOR_CFLAGS) \
72 -DDATADIR="\"$(pkgdatadir)\"" \
73 -Wall -Werror \
74 -DG_LOG_DOMAIN=\"indicator-application-service\"
75
76indicator_application_service_LDADD = \
77 $(INDICATOR_LIBS) \
78 libappindicator$(VER).la
7931
80glib_marshal_list = application-service-marshal.list32glib_marshal_list = application-service-marshal.list
81glib_marshal_prefix = _application_service_marshal33glib_marshal_prefix = _application_service_marshal
@@ -111,6 +63,7 @@
111 app-indicator-enum-types.c \63 app-indicator-enum-types.c \
112 app-indicator.c \64 app-indicator.c \
113 application-service-marshal.c \65 application-service-marshal.c \
66 dbus-shared.h \
114 generate-id.h \67 generate-id.h \
115 generate-id.c68 generate-id.c
11669
@@ -143,9 +96,6 @@
143##################################96##################################
14497
145DBUS_SPECS = \98DBUS_SPECS = \
146 dbus-properties.xml \
147 application-service.xml \
148 notification-approver.xml \
149 notification-item.xml \99 notification-item.xml \
150 notification-watcher.xml100 notification-watcher.xml
151101
@@ -202,7 +152,7 @@
202AppIndicator_0_1_gir_INCLUDES = \152AppIndicator_0_1_gir_INCLUDES = \
203 GObject-2.0 \153 GObject-2.0 \
204 $(GTKGIR)154 $(GTKGIR)
205AppIndicator_0_1_gir_CFLAGS = $(INDICATOR_CFLAGS) -I$(srcdir) -I$(top_builddir)/src155AppIndicator_0_1_gir_CFLAGS = $(LIBRARY_CFLAGS) -I$(srcdir) -I$(top_builddir)/src
206AppIndicator_0_1_gir_LIBS = libappindicator$(VER).la156AppIndicator_0_1_gir_LIBS = libappindicator$(VER).la
207AppIndicator_0_1_gir_FILES = $(introspection_sources)157AppIndicator_0_1_gir_FILES = $(introspection_sources)
208158
209159
=== removed file 'src/application-service-appstore.c'
--- src/application-service-appstore.c 2010-10-08 15:02:24 +0000
+++ src/application-service-appstore.c 1970-01-01 00:00:00 +0000
@@ -1,1305 +0,0 @@
1/*
2An object that stores the registration of all the application
3indicators. It also communicates this to the indicator visualization.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <dbus/dbus-glib.h>
28#include "app-indicator.h"
29#include "app-indicator-enum-types.h"
30#include "application-service-appstore.h"
31#include "application-service-marshal.h"
32#include "dbus-properties-client.h"
33#include "dbus-shared.h"
34#include "notification-approver-client.h"
35#include "generate-id.h"
36
37/* DBus Prototypes */
38static gboolean _application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error);
39
40#include "application-service-server.h"
41
42#define NOTIFICATION_ITEM_PROP_ID "Id"
43#define NOTIFICATION_ITEM_PROP_CATEGORY "Category"
44#define NOTIFICATION_ITEM_PROP_STATUS "Status"
45#define NOTIFICATION_ITEM_PROP_ICON_NAME "IconName"
46#define NOTIFICATION_ITEM_PROP_AICON_NAME "AttentionIconName"
47#define NOTIFICATION_ITEM_PROP_ICON_THEME_PATH "IconThemePath"
48#define NOTIFICATION_ITEM_PROP_MENU "Menu"
49#define NOTIFICATION_ITEM_PROP_LABEL "XAyatanaLabel"
50#define NOTIFICATION_ITEM_PROP_LABEL_GUIDE "XAyatanaLabelGuide"
51#define NOTIFICATION_ITEM_PROP_ORDERING_INDEX "XAyatanaOrderingIndex"
52
53#define NOTIFICATION_ITEM_SIG_NEW_ICON "NewIcon"
54#define NOTIFICATION_ITEM_SIG_NEW_AICON "NewAttentionIcon"
55#define NOTIFICATION_ITEM_SIG_NEW_STATUS "NewStatus"
56#define NOTIFICATION_ITEM_SIG_NEW_LABEL "XAyatanaNewLabel"
57#define NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH "NewIconThemePath"
58
59#define OVERRIDE_GROUP_NAME "Ordering Index Overrides"
60#define OVERRIDE_FILE_NAME "ordering-override.keyfile"
61
62/* Private Stuff */
63struct _ApplicationServiceAppstorePrivate {
64 DBusGConnection * bus;
65 GList * applications;
66 GList * approvers;
67 GHashTable * ordering_overrides;
68};
69
70typedef enum {
71 VISIBLE_STATE_HIDDEN,
72 VISIBLE_STATE_SHOWN
73} visible_state_t;
74
75#define STATE2STRING(x) ((x) == VISIBLE_STATE_HIDDEN ? "hidden" : "visible")
76
77typedef struct _Approver Approver;
78struct _Approver {
79 DBusGProxy * proxy;
80 gboolean destroy_by_proxy;
81};
82
83typedef struct _Application Application;
84struct _Application {
85 gchar * id;
86 gchar * category;
87 gchar * dbus_name;
88 gchar * dbus_object;
89 ApplicationServiceAppstore * appstore; /* not ref'd */
90 DBusGProxy * dbus_proxy;
91 DBusGProxy * prop_proxy;
92 gboolean validated; /* Whether we've gotten all the parameters and they look good. */
93 AppIndicatorStatus status;
94 gchar * icon;
95 gchar * aicon;
96 gchar * menu;
97 gchar * icon_theme_path;
98 gchar * label;
99 gchar * guide;
100 gboolean currently_free;
101 guint ordering_index;
102 GList * approved_by;
103 visible_state_t visible_state;
104};
105
106#define APPLICATION_SERVICE_APPSTORE_GET_PRIVATE(o) \
107 (G_TYPE_INSTANCE_GET_PRIVATE ((o), APPLICATION_SERVICE_APPSTORE_TYPE, ApplicationServiceAppstorePrivate))
108
109/* Signals Stuff */
110enum {
111 APPLICATION_ADDED,
112 APPLICATION_REMOVED,
113 APPLICATION_ICON_CHANGED,
114 APPLICATION_LABEL_CHANGED,
115 APPLICATION_ICON_THEME_PATH_CHANGED,
116 LAST_SIGNAL
117};
118
119static guint signals[LAST_SIGNAL] = { 0 };
120
121/* GObject stuff */
122static void application_service_appstore_class_init (ApplicationServiceAppstoreClass *klass);
123static void application_service_appstore_init (ApplicationServiceAppstore *self);
124static void application_service_appstore_dispose (GObject *object);
125static void application_service_appstore_finalize (GObject *object);
126static gint app_sort_func (gconstpointer a, gconstpointer b, gpointer userdata);
127static void load_override_file (GHashTable * hash, const gchar * filename);
128static AppIndicatorStatus string_to_status(const gchar * status_string);
129static void apply_status (Application * app);
130static AppIndicatorCategory string_to_cat(const gchar * cat_string);
131static void approver_free (gpointer papprover, gpointer user_data);
132static void check_with_new_approver (gpointer papp, gpointer papprove);
133static void check_with_old_approver (gpointer papprove, gpointer papp);
134static Application * find_application (ApplicationServiceAppstore * appstore, const gchar * address, const gchar * object);
135
136G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
137
138static void
139application_service_appstore_class_init (ApplicationServiceAppstoreClass *klass)
140{
141 GObjectClass *object_class = G_OBJECT_CLASS (klass);
142
143 g_type_class_add_private (klass, sizeof (ApplicationServiceAppstorePrivate));
144
145 object_class->dispose = application_service_appstore_dispose;
146 object_class->finalize = application_service_appstore_finalize;
147
148 signals[APPLICATION_ADDED] = g_signal_new ("application-added",
149 G_TYPE_FROM_CLASS(klass),
150 G_SIGNAL_RUN_LAST,
151 G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_added),
152 NULL, NULL,
153 _application_service_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
154 G_TYPE_NONE, 7, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE);
155 signals[APPLICATION_REMOVED] = g_signal_new ("application-removed",
156 G_TYPE_FROM_CLASS(klass),
157 G_SIGNAL_RUN_LAST,
158 G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_removed),
159 NULL, NULL,
160 g_cclosure_marshal_VOID__INT,
161 G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE);
162 signals[APPLICATION_ICON_CHANGED] = g_signal_new ("application-icon-changed",
163 G_TYPE_FROM_CLASS(klass),
164 G_SIGNAL_RUN_LAST,
165 G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_icon_changed),
166 NULL, NULL,
167 _application_service_marshal_VOID__INT_STRING,
168 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING, G_TYPE_NONE);
169 signals[APPLICATION_ICON_THEME_PATH_CHANGED] = g_signal_new ("application-icon-theme-path-changed",
170 G_TYPE_FROM_CLASS(klass),
171 G_SIGNAL_RUN_LAST,
172 G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_icon_theme_path_changed),
173 NULL, NULL,
174 _application_service_marshal_VOID__INT_STRING,
175 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING, G_TYPE_NONE);
176 signals[APPLICATION_LABEL_CHANGED] = g_signal_new ("application-label-changed",
177 G_TYPE_FROM_CLASS(klass),
178 G_SIGNAL_RUN_LAST,
179 G_STRUCT_OFFSET (ApplicationServiceAppstoreClass, application_label_changed),
180 NULL, NULL,
181 _application_service_marshal_VOID__INT_STRING_STRING,
182 G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_NONE);
183
184 dbus_g_object_register_marshaller(_application_service_marshal_VOID__STRING_STRING,
185 G_TYPE_NONE,
186 G_TYPE_STRING,
187 G_TYPE_STRING,
188 G_TYPE_INVALID);
189 dbus_g_object_register_marshaller(_application_service_marshal_VOID__BOOLEAN_STRING_OBJECT,
190 G_TYPE_NONE,
191 G_TYPE_BOOLEAN,
192 G_TYPE_STRING,
193 G_TYPE_OBJECT,
194 G_TYPE_INVALID);
195
196 dbus_g_object_type_install_info(APPLICATION_SERVICE_APPSTORE_TYPE,
197 &dbus_glib__application_service_server_object_info);
198
199 return;
200}
201
202static void
203application_service_appstore_init (ApplicationServiceAppstore *self)
204{
205
206 ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (self);
207
208 priv->applications = NULL;
209 priv->approvers = NULL;
210
211 priv->ordering_overrides = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
212
213 load_override_file(priv->ordering_overrides, DATADIR "/" OVERRIDE_FILE_NAME);
214 gchar * userfile = g_build_filename(g_get_user_data_dir(), "indicators", "application", OVERRIDE_FILE_NAME, NULL);
215 load_override_file(priv->ordering_overrides, userfile);
216 g_free(userfile);
217
218 GError * error = NULL;
219 priv->bus = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
220 if (error != NULL) {
221 g_error("Unable to get session bus: %s", error->message);
222 g_error_free(error);
223 return;
224 }
225
226 dbus_g_connection_register_g_object(priv->bus,
227 INDICATOR_APPLICATION_DBUS_OBJ,
228 G_OBJECT(self));
229
230 self->priv = priv;
231
232 return;
233}
234
235static void
236application_service_appstore_dispose (GObject *object)
237{
238 ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE(object)->priv;
239
240 while (priv->applications != NULL) {
241 application_service_appstore_application_remove(APPLICATION_SERVICE_APPSTORE(object),
242 ((Application *)priv->applications->data)->dbus_name,
243 ((Application *)priv->applications->data)->dbus_object);
244 }
245
246 if (priv->approvers != NULL) {
247 g_list_foreach(priv->approvers, approver_free, object);
248 g_list_free(priv->approvers);
249 priv->approvers = NULL;
250 }
251
252 G_OBJECT_CLASS (application_service_appstore_parent_class)->dispose (object);
253 return;
254}
255
256static void
257application_service_appstore_finalize (GObject *object)
258{
259 ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE(object)->priv;
260
261 if (priv->ordering_overrides != NULL) {
262 g_hash_table_destroy(priv->ordering_overrides);
263 priv->ordering_overrides = NULL;
264 }
265
266 G_OBJECT_CLASS (application_service_appstore_parent_class)->finalize (object);
267 return;
268}
269
270/* Loads the file and adds the override entries to the table
271 of overrides */
272static void
273load_override_file (GHashTable * hash, const gchar * filename)
274{
275 g_return_if_fail(hash != NULL);
276 g_return_if_fail(filename != NULL);
277
278 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
279 return;
280 }
281
282 g_debug("Loading overrides from: '%s'", filename);
283
284 GError * error = NULL;
285 GKeyFile * keyfile = g_key_file_new();
286 g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_NONE, &error);
287
288 if (error != NULL) {
289 g_warning("Unable to load keyfile '%s' because: %s", filename, error->message);
290 g_error_free(error);
291 g_key_file_free(keyfile);
292 return;
293 }
294
295 gchar ** keys = g_key_file_get_keys(keyfile, OVERRIDE_GROUP_NAME, NULL, &error);
296 if (error != NULL) {
297 g_warning("Unable to get keys from keyfile '%s' because: %s", filename, error->message);
298 g_error_free(error);
299 g_key_file_free(keyfile);
300 return;
301 }
302
303 gchar * key = keys[0];
304 gint i;
305
306 for (i = 0; (key = keys[i]) != NULL; i++) {
307 GError * valerror = NULL;
308 gint val = g_key_file_get_integer(keyfile, OVERRIDE_GROUP_NAME, key, &valerror);
309
310 if (valerror != NULL) {
311 g_warning("Unable to get key '%s' out of file '%s' because: %s", key, filename, valerror->message);
312 g_error_free(valerror);
313 continue;
314 }
315 g_debug("%s: override '%s' with value '%d'", filename, key, val);
316
317 g_hash_table_insert(hash, g_strdup(key), GINT_TO_POINTER(val));
318 }
319 g_strfreev(keys);
320 g_key_file_free(keyfile);
321
322 return;
323}
324
325/* Return from getting the properties from the item. We're looking at those
326 and making sure we have everythign that we need. If we do, then we'll
327 move on up to sending this onto the indicator. */
328static void
329get_all_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
330{
331 if (error != NULL) {
332 g_warning("Unable to get properties: %s", error->message);
333 /* TODO: We need to free all the application data here */
334 return;
335 }
336
337 Application * app = (Application *)data;
338
339 if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU) == NULL ||
340 g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ID) == NULL ||
341 g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_CATEGORY) == NULL ||
342 g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS) == NULL ||
343 g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME) == NULL) {
344 g_warning("Notification Item on object %s of %s doesn't have enough properties.", app->dbus_object, app->dbus_name);
345 g_free(app); // Need to do more than this, but it gives the idea of the flow we're going for.
346 return;
347 }
348
349 app->validated = TRUE;
350
351 app->id = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ID));
352 app->category = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_CATEGORY));
353 app->status = string_to_status(g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS)));
354
355 ApplicationServiceAppstorePrivate * priv = app->appstore->priv;
356
357 app->icon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_NAME));
358
359 GValue * menuval = (GValue *)g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_MENU);
360 if (G_VALUE_TYPE(menuval) == G_TYPE_STRING) {
361 /* This is here to support an older version where we
362 were using strings instea of object paths. */
363 app->menu = g_value_dup_string(menuval);
364 } else {
365 app->menu = g_strdup((gchar *)g_value_get_boxed(menuval));
366 }
367
368 if (g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME) != NULL) {
369 app->aicon = g_value_dup_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_AICON_NAME));
370 }
371
372 gpointer icon_theme_path_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ICON_THEME_PATH);
373 if (icon_theme_path_data != NULL) {
374 app->icon_theme_path = g_value_dup_string((GValue *)icon_theme_path_data);
375 } else {
376 app->icon_theme_path = g_strdup("");
377 }
378
379 gpointer ordering_index_over = g_hash_table_lookup(priv->ordering_overrides, app->id);
380 if (ordering_index_over == NULL) {
381 gpointer ordering_index_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_ORDERING_INDEX);
382 if (ordering_index_data == NULL || g_value_get_uint(ordering_index_data) == 0) {
383 app->ordering_index = generate_id(string_to_cat(app->category), app->id);
384 } else {
385 app->ordering_index = g_value_get_uint(ordering_index_data);
386 }
387 } else {
388 app->ordering_index = GPOINTER_TO_UINT(ordering_index_over);
389 }
390 g_debug("'%s' ordering index is '%X'", app->id, app->ordering_index);
391
392 gpointer label_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_LABEL);
393 if (label_data != NULL) {
394 app->label = g_value_dup_string((GValue *)label_data);
395 } else {
396 app->label = g_strdup("");
397 }
398
399 gpointer guide_data = g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_LABEL_GUIDE);
400 if (guide_data != NULL) {
401 app->guide = g_value_dup_string((GValue *)guide_data);
402 } else {
403 app->guide = g_strdup("");
404 }
405
406 priv->applications = g_list_insert_sorted_with_data (priv->applications, app, app_sort_func, NULL);
407 g_list_foreach(priv->approvers, check_with_old_approver, app);
408
409 apply_status(app);
410
411 return;
412}
413
414/* Check the application against an approver */
415static void
416check_with_old_approver (gpointer papprove, gpointer papp)
417{
418 /* Funny the parallels, eh? */
419 check_with_new_approver(papp, papprove);
420 return;
421}
422
423/* Simple translation function -- could be optimized */
424static AppIndicatorStatus
425string_to_status(const gchar * status_string)
426{
427 GEnumClass * klass = G_ENUM_CLASS(g_type_class_ref(APP_INDICATOR_TYPE_INDICATOR_STATUS));
428 g_return_val_if_fail(klass != NULL, APP_INDICATOR_STATUS_PASSIVE);
429
430 AppIndicatorStatus retval = APP_INDICATOR_STATUS_PASSIVE;
431
432 GEnumValue * val = g_enum_get_value_by_nick(klass, status_string);
433 if (val == NULL) {
434 g_warning("Unrecognized status '%s' assuming passive.", status_string);
435 } else {
436 retval = (AppIndicatorStatus)val->value;
437 }
438
439 g_type_class_unref(klass);
440
441 return retval;
442}
443
444/* Simple translation function -- could be optimized */
445static AppIndicatorCategory
446string_to_cat(const gchar * cat_string)
447{
448 GEnumClass * klass = G_ENUM_CLASS(g_type_class_ref(APP_INDICATOR_TYPE_INDICATOR_CATEGORY));
449 g_return_val_if_fail(klass != NULL, APP_INDICATOR_CATEGORY_OTHER);
450
451 AppIndicatorCategory retval = APP_INDICATOR_CATEGORY_OTHER;
452
453 GEnumValue * val = g_enum_get_value_by_nick(klass, cat_string);
454 if (val == NULL) {
455 g_warning("Unrecognized status '%s' assuming other.", cat_string);
456 } else {
457 retval = (AppIndicatorCategory)val->value;
458 }
459
460 g_type_class_unref(klass);
461
462 return retval;
463}
464
465
466/* A small helper function to get the position of an application
467 in the app list of the applications that are visible. */
468static gint
469get_position (Application * app) {
470 ApplicationServiceAppstore * appstore = app->appstore;
471 ApplicationServiceAppstorePrivate * priv = appstore->priv;
472
473 GList * lapp;
474 gint count;
475
476 /* Go through the list and try to find ours */
477 for (lapp = priv->applications, count = 0; lapp != NULL; lapp = g_list_next(lapp), count++) {
478 if (lapp->data == app) {
479 break;
480 }
481
482 /* If the selected app isn't visible let's not
483 count it's position */
484 Application * thisapp = (Application *)(lapp->data);
485 if (thisapp->visible_state == VISIBLE_STATE_HIDDEN) {
486 count--;
487 }
488 }
489
490 if (lapp == NULL) {
491 g_warning("Unable to find position for app '%s'", app->id);
492 return -1;
493 }
494
495 return count;
496}
497
498/* A simple global function for dealing with freeing the information
499 in an Application structure */
500static void
501application_free (Application * app)
502{
503 if (app == NULL) return;
504 g_debug("Application free '%s'", app->id);
505
506 /* Handle the case where this could be called by unref'ing one of
507 the proxy objects. */
508 if (app->currently_free) return;
509 app->currently_free = TRUE;
510
511 if (app->dbus_proxy) {
512 g_object_unref(app->dbus_proxy);
513 }
514 if (app->prop_proxy) {
515 g_object_unref(app->prop_proxy);
516 }
517
518 if (app->id != NULL) {
519 g_free(app->id);
520 }
521 if (app->category != NULL) {
522 g_free(app->category);
523 }
524 if (app->dbus_name != NULL) {
525 g_free(app->dbus_name);
526 }
527 if (app->dbus_object != NULL) {
528 g_free(app->dbus_object);
529 }
530 if (app->icon != NULL) {
531 g_free(app->icon);
532 }
533 if (app->aicon != NULL) {
534 g_free(app->aicon);
535 }
536 if (app->menu != NULL) {
537 g_free(app->menu);
538 }
539 if (app->icon_theme_path != NULL) {
540 g_free(app->icon_theme_path);
541 }
542 if (app->label != NULL) {
543 g_free(app->label);
544 }
545 if (app->guide != NULL) {
546 g_free(app->guide);
547 }
548 if (app->approved_by != NULL) {
549 g_list_free(app->approved_by);
550 }
551
552 g_free(app);
553 return;
554}
555
556/* Gets called when the proxy is destroyed, which is usually when it
557 drops off of the bus. */
558static void
559application_removed_cb (DBusGProxy * proxy, gpointer userdata)
560{
561 Application * app = (Application *)userdata;
562 g_debug("Application proxy destroyed '%s'", app->id);
563
564 /* Remove from the panel */
565 app->status = APP_INDICATOR_STATUS_PASSIVE;
566 apply_status(app);
567
568 /* Remove from the application list */
569 app->appstore->priv->applications = g_list_remove(app->appstore->priv->applications, app);
570
571 /* Destroy the data */
572 application_free(app);
573 return;
574}
575
576/* This function takes two Application structure
577 pointers and uses their ordering index to compare them. */
578static gint
579app_sort_func (gconstpointer a, gconstpointer b, gpointer userdata)
580{
581 Application * appa = (Application *)a;
582 Application * appb = (Application *)b;
583 return (appb->ordering_index/2) - (appa->ordering_index/2);
584}
585
586/* Change the status of the application. If we're going passive
587 it removes it from the panel. If we're coming online, then
588 it add it to the panel. Otherwise it changes the icon. */
589static void
590apply_status (Application * app)
591{
592 ApplicationServiceAppstore * appstore = app->appstore;
593 ApplicationServiceAppstorePrivate * priv = appstore->priv;
594
595 /* g_debug("Applying status. Status: %d Approved by: %d Approvers: %d Visible: %d", app->status, g_list_length(app->approved_by), g_list_length(priv->approvers), app->visible_state); */
596
597 visible_state_t goal_state = VISIBLE_STATE_HIDDEN;
598
599 if (app->status != APP_INDICATOR_STATUS_PASSIVE &&
600 g_list_length(app->approved_by) >= g_list_length(priv->approvers)) {
601 goal_state = VISIBLE_STATE_SHOWN;
602 }
603
604 /* Nothing needs to change, we're good */
605 if (app->visible_state == goal_state /* ) { */
606 && goal_state == VISIBLE_STATE_HIDDEN) {
607 /* TODO: Uhg, this is a little wrong in that we're going to
608 send an icon every time the status changes and the indicator
609 is visible even though it might not be updating. But, at
610 this point we need a small patch that is harmless. In the
611 future we need to track which icon is shown and remove the
612 duplicate message. */
613 return;
614 }
615
616 g_debug("Changing app '%s' state from %s to %s", app->id, STATE2STRING(app->visible_state), STATE2STRING(goal_state));
617
618 /* This means we're going off line */
619 if (goal_state == VISIBLE_STATE_HIDDEN) {
620 gint position = get_position(app);
621 if (position == -1) return;
622
623 g_signal_emit(G_OBJECT(appstore),
624 signals[APPLICATION_REMOVED], 0,
625 position, TRUE);
626 } else {
627 /* Figure out which icon we should be using */
628 gchar * newicon = app->icon;
629 if (app->status == APP_INDICATOR_STATUS_ATTENTION && app->aicon != NULL && app->aicon[0] != '\0') {
630 newicon = app->aicon;
631 }
632
633 /* Determine whether we're already shown or not */
634 if (app->visible_state == VISIBLE_STATE_HIDDEN) {
635 /* Put on panel */
636 g_signal_emit(G_OBJECT(app->appstore),
637 signals[APPLICATION_ADDED], 0,
638 newicon,
639 get_position(app), /* Position */
640 app->dbus_name,
641 app->menu,
642 app->icon_theme_path,
643 app->label,
644 app->guide,
645 TRUE);
646 } else {
647 /* Icon update */
648 gint position = get_position(app);
649 if (position == -1) return;
650
651 g_signal_emit(G_OBJECT(appstore),
652 signals[APPLICATION_ICON_CHANGED], 0,
653 position, newicon, TRUE);
654 }
655 }
656
657 app->visible_state = goal_state;
658
659 return;
660}
661
662/* Gets the data back on an updated icon signal. Hopefully
663 a new fun icon. */
664static void
665new_icon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
666{
667 /* Check for errors */
668 if (error != NULL) {
669 g_warning("Unable to get updated icon name: %s", error->message);
670 return;
671 }
672
673 /* Grab the icon and make sure we have one */
674 const gchar * newicon = g_value_get_string(&value);
675 if (newicon == NULL) {
676 g_warning("Bad new icon :(");
677 return;
678 }
679
680 Application * app = (Application *) userdata;
681
682 if (g_strcmp0(newicon, app->icon)) {
683 /* If the new icon is actually a new icon */
684 if (app->icon != NULL) g_free(app->icon);
685 app->icon = g_strdup(newicon);
686
687 if (app->visible_state == VISIBLE_STATE_SHOWN && app->status == APP_INDICATOR_STATUS_ACTIVE) {
688 gint position = get_position(app);
689 if (position == -1) return;
690
691 g_signal_emit(G_OBJECT(app->appstore),
692 signals[APPLICATION_ICON_CHANGED], 0,
693 position, newicon, TRUE);
694 }
695 }
696
697 return;
698}
699
700/* Gets the data back on an updated aicon signal. Hopefully
701 a new fun icon. */
702static void
703new_aicon_cb (DBusGProxy * proxy, GValue value, GError * error, gpointer userdata)
704{
705 /* Check for errors */
706 if (error != NULL) {
707 g_warning("Unable to get updated icon name: %s", error->message);
708 return;
709 }
710
711 /* Grab the icon and make sure we have one */
712 const gchar * newicon = g_value_get_string(&value);
713 if (newicon == NULL) {
714 g_warning("Bad new icon :(");
715 return;
716 }
717
718 Application * app = (Application *) userdata;
719
720 if (g_strcmp0(newicon, app->aicon)) {
721 /* If the new icon is actually a new icon */
722 if (app->aicon != NULL) g_free(app->aicon);
723 app->aicon = g_strdup(newicon);
724
725 if (app->visible_state == VISIBLE_STATE_SHOWN && app->status == APP_INDICATOR_STATUS_ATTENTION) {
726 gint position = get_position(app);
727 if (position == -1) return;
728
729 g_signal_emit(G_OBJECT(app->appstore),
730 signals[APPLICATION_ICON_CHANGED], 0,
731 position, newicon, TRUE);
732 }
733 }
734
735 return;
736}
737
738/* Called when the Notification Item signals that it
739 has a new icon. */
740static void
741new_icon (DBusGProxy * proxy, gpointer data)
742{
743 Application * app = (Application *)data;
744 if (!app->validated) return;
745
746 org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
747 NOTIFICATION_ITEM_DBUS_IFACE,
748 NOTIFICATION_ITEM_PROP_ICON_NAME,
749 new_icon_cb,
750 app);
751 return;
752}
753
754/* Called when the Notification Item signals that it
755 has a new attention icon. */
756static void
757new_aicon (DBusGProxy * proxy, gpointer data)
758{
759 Application * app = (Application *)data;
760 if (!app->validated) return;
761
762 org_freedesktop_DBus_Properties_get_async(app->prop_proxy,
763 NOTIFICATION_ITEM_DBUS_IFACE,
764 NOTIFICATION_ITEM_PROP_AICON_NAME,
765 new_aicon_cb,
766 app);
767
768 return;
769}
770
771/* Called when the Notification Item signals that it
772 has a new status. */
773static void
774new_status (DBusGProxy * proxy, const gchar * status, gpointer data)
775{
776 Application * app = (Application *)data;
777 if (!app->validated) return;
778
779 app->status = string_to_status(status);
780 apply_status(app);
781
782 return;
783}
784
785/* Called when the Notification Item signals that it
786 has a new icon theme path. */
787static void
788new_icon_theme_path (DBusGProxy * proxy, const gchar * icon_theme_path, gpointer data)
789{
790 Application * app = (Application *)data;
791 if (!app->validated) return;
792
793 if (g_strcmp0(icon_theme_path, app->icon_theme_path)) {
794 /* If the new icon theme path is actually a new icon theme path */
795 if (app->icon_theme_path != NULL) g_free(app->icon_theme_path);
796 app->icon_theme_path = g_strdup(icon_theme_path);
797
798 if (app->visible_state != VISIBLE_STATE_HIDDEN) {
799 gint position = get_position(app);
800 if (position == -1) return;
801
802 g_signal_emit(G_OBJECT(app->appstore),
803 signals[APPLICATION_ICON_THEME_PATH_CHANGED], 0,
804 position, app->icon_theme_path, TRUE);
805 }
806 }
807
808 return;
809}
810
811/* Called when the Notification Item signals that it
812 has a new label. */
813static void
814new_label (DBusGProxy * proxy, const gchar * label, const gchar * guide, gpointer data)
815{
816 Application * app = (Application *)data;
817 if (!app->validated) return;
818
819 gboolean changed = FALSE;
820
821 if (g_strcmp0(app->label, label) != 0) {
822 changed = TRUE;
823 if (app->label != NULL) {
824 g_free(app->label);
825 app->label = NULL;
826 }
827 app->label = g_strdup(label);
828 }
829
830 if (g_strcmp0(app->guide, guide) != 0) {
831 changed = TRUE;
832 if (app->guide != NULL) {
833 g_free(app->guide);
834 app->guide = NULL;
835 }
836 app->guide = g_strdup(guide);
837 }
838
839 if (changed) {
840 gint position = get_position(app);
841 if (position == -1) return;
842
843 g_signal_emit(app->appstore, signals[APPLICATION_LABEL_CHANGED], 0,
844 position,
845 app->label != NULL ? app->label : "",
846 app->guide != NULL ? app->guide : "",
847 TRUE);
848 }
849
850 return;
851}
852
853/* Adding a new NotificationItem object from DBus in to the
854 appstore. First, we need to get the information on it
855 though. */
856void
857application_service_appstore_application_add (ApplicationServiceAppstore * appstore, const gchar * dbus_name, const gchar * dbus_object)
858{
859 g_debug("Adding new application: %s:%s", dbus_name, dbus_object);
860
861 /* Make sure we got a sensible request */
862 g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(appstore));
863 g_return_if_fail(dbus_name != NULL && dbus_name[0] != '\0');
864 g_return_if_fail(dbus_object != NULL && dbus_object[0] != '\0');
865 ApplicationServiceAppstorePrivate * priv = appstore->priv;
866 Application * app = find_application(appstore, dbus_name, dbus_object);
867
868 if (app != NULL) {
869 g_warning("Application already exists! Rerequesting properties.");
870 org_freedesktop_DBus_Properties_get_all_async(app->prop_proxy,
871 NOTIFICATION_ITEM_DBUS_IFACE,
872 get_all_properties_cb,
873 app);
874 return;
875 }
876
877 /* Build the application entry. This will be carried
878 along until we're sure we've got everything. */
879 app = g_new0(Application, 1);
880
881 app->validated = FALSE;
882 app->dbus_name = g_strdup(dbus_name);
883 app->dbus_object = g_strdup(dbus_object);
884 app->appstore = appstore;
885 app->status = APP_INDICATOR_STATUS_PASSIVE;
886 app->icon = NULL;
887 app->aicon = NULL;
888 app->menu = NULL;
889 app->icon_theme_path = NULL;
890 app->label = NULL;
891 app->guide = NULL;
892 app->currently_free = FALSE;
893 app->ordering_index = 0;
894 app->approved_by = NULL;
895 app->visible_state = VISIBLE_STATE_HIDDEN;
896
897 /* Get the DBus proxy for the NotificationItem interface */
898 GError * error = NULL;
899 app->dbus_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
900 app->dbus_name,
901 app->dbus_object,
902 NOTIFICATION_ITEM_DBUS_IFACE,
903 &error);
904
905 if (error != NULL) {
906 g_warning("Unable to get notification item proxy for object '%s' on host '%s': %s", dbus_object, dbus_name, error->message);
907 g_error_free(error);
908 g_free(app);
909 return;
910 }
911
912 /* We've got it, let's watch it for destruction */
913 g_signal_connect(G_OBJECT(app->dbus_proxy), "destroy", G_CALLBACK(application_removed_cb), app);
914
915 /* Grab the property proxy interface */
916 app->prop_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
917 app->dbus_name,
918 app->dbus_object,
919 DBUS_INTERFACE_PROPERTIES,
920 &error);
921
922 if (error != NULL) {
923 g_warning("Unable to get property proxy for object '%s' on host '%s': %s", dbus_object, dbus_name, error->message);
924 g_error_free(error);
925 g_object_unref(app->dbus_proxy);
926 g_free(app);
927 return;
928 }
929
930 /* Connect to signals */
931 dbus_g_proxy_add_signal(app->dbus_proxy,
932 NOTIFICATION_ITEM_SIG_NEW_ICON,
933 G_TYPE_INVALID);
934 dbus_g_proxy_add_signal(app->dbus_proxy,
935 NOTIFICATION_ITEM_SIG_NEW_AICON,
936 G_TYPE_INVALID);
937 dbus_g_proxy_add_signal(app->dbus_proxy,
938 NOTIFICATION_ITEM_SIG_NEW_STATUS,
939 G_TYPE_STRING,
940 G_TYPE_INVALID);
941 dbus_g_proxy_add_signal(app->dbus_proxy,
942 NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH,
943 G_TYPE_STRING,
944 G_TYPE_INVALID);
945 dbus_g_proxy_add_signal(app->dbus_proxy,
946 NOTIFICATION_ITEM_SIG_NEW_LABEL,
947 G_TYPE_STRING,
948 G_TYPE_STRING,
949 G_TYPE_INVALID);
950
951 dbus_g_proxy_connect_signal(app->dbus_proxy,
952 NOTIFICATION_ITEM_SIG_NEW_ICON,
953 G_CALLBACK(new_icon),
954 app,
955 NULL);
956 dbus_g_proxy_connect_signal(app->dbus_proxy,
957 NOTIFICATION_ITEM_SIG_NEW_AICON,
958 G_CALLBACK(new_aicon),
959 app,
960 NULL);
961 dbus_g_proxy_connect_signal(app->dbus_proxy,
962 NOTIFICATION_ITEM_SIG_NEW_STATUS,
963 G_CALLBACK(new_status),
964 app,
965 NULL);
966 dbus_g_proxy_connect_signal(app->dbus_proxy,
967 NOTIFICATION_ITEM_SIG_NEW_ICON_THEME_PATH,
968 G_CALLBACK(new_icon_theme_path),
969 app,
970 NULL);
971 dbus_g_proxy_connect_signal(app->dbus_proxy,
972 NOTIFICATION_ITEM_SIG_NEW_LABEL,
973 G_CALLBACK(new_label),
974 app,
975 NULL);
976
977 /* Get all the propertiees */
978 org_freedesktop_DBus_Properties_get_all_async(app->prop_proxy,
979 NOTIFICATION_ITEM_DBUS_IFACE,
980 get_all_properties_cb,
981 app);
982
983 /* We're returning, nothing is yet added until the properties
984 come back and give us more info. */
985 return;
986}
987
988/* Looks for an application in the list of applications */
989static Application *
990find_application (ApplicationServiceAppstore * appstore, const gchar * address, const gchar * object)
991{
992 ApplicationServiceAppstorePrivate * priv = appstore->priv;
993 GList * listpntr;
994
995 for (listpntr = priv->applications; listpntr != NULL; listpntr = g_list_next(listpntr)) {
996 Application * app = (Application *)listpntr->data;
997
998 if (!g_strcmp0(app->dbus_name, address) && !g_strcmp0(app->dbus_object, object)) {
999 return app;
1000 }
1001 }
1002
1003 return NULL;
1004}
1005
1006/* Removes an application. Currently only works for the apps
1007 that are shown. */
1008void
1009application_service_appstore_application_remove (ApplicationServiceAppstore * appstore, const gchar * dbus_name, const gchar * dbus_object)
1010{
1011 g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(appstore));
1012 g_return_if_fail(dbus_name != NULL && dbus_name[0] != '\0');
1013 g_return_if_fail(dbus_object != NULL && dbus_object[0] != '\0');
1014
1015 Application * app = find_application(appstore, dbus_name, dbus_object);
1016 if (app != NULL) {
1017 application_removed_cb(NULL, app);
1018 } else {
1019 g_warning("Unable to find application %s:%s", dbus_name, dbus_object);
1020 }
1021
1022 return;
1023}
1024
1025gchar**
1026application_service_appstore_application_get_list (ApplicationServiceAppstore * appstore)
1027{
1028 ApplicationServiceAppstorePrivate * priv = appstore->priv;
1029 gchar ** out;
1030 gchar ** outpntr;
1031 GList * listpntr;
1032
1033 out = g_new(gchar*, g_list_length(priv->applications) + 1);
1034
1035 for (listpntr = priv->applications, outpntr = out; listpntr != NULL; listpntr = g_list_next(listpntr), ++outpntr) {
1036 Application * app = (Application *)listpntr->data;
1037 *outpntr = g_strdup_printf("%s%s", app->dbus_name, app->dbus_object);
1038 }
1039 *outpntr = 0;
1040 return out;
1041}
1042
1043/* Creates a basic appstore object and attaches the
1044 LRU file object to it. */
1045ApplicationServiceAppstore *
1046application_service_appstore_new (void)
1047{
1048 ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(g_object_new(APPLICATION_SERVICE_APPSTORE_TYPE, NULL));
1049 return appstore;
1050}
1051
1052/* DBus Interface */
1053static gboolean
1054_application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error)
1055{
1056 ApplicationServiceAppstorePrivate * priv = appstore->priv;
1057
1058 *apps = g_ptr_array_new();
1059 GList * listpntr;
1060 gint position = 0;
1061
1062 for (listpntr = priv->applications; listpntr != NULL; listpntr = g_list_next(listpntr)) {
1063 Application * app = (Application *)listpntr->data;
1064 if (app->visible_state == VISIBLE_STATE_HIDDEN) {
1065 continue;
1066 }
1067
1068 GValueArray * values = g_value_array_new(5);
1069
1070 GValue value = {0};
1071
1072 /* Icon name */
1073 g_value_init(&value, G_TYPE_STRING);
1074 g_value_set_string(&value, app->icon);
1075 g_value_array_append(values, &value);
1076 g_value_unset(&value);
1077
1078 /* Position */
1079 g_value_init(&value, G_TYPE_INT);
1080 g_value_set_int(&value, position++);
1081 g_value_array_append(values, &value);
1082 g_value_unset(&value);
1083
1084 /* DBus Address */
1085 g_value_init(&value, G_TYPE_STRING);
1086 g_value_set_string(&value, app->dbus_name);
1087 g_value_array_append(values, &value);
1088 g_value_unset(&value);
1089
1090 /* DBus Object */
1091 g_value_init(&value, DBUS_TYPE_G_OBJECT_PATH);
1092 g_value_set_static_boxed(&value, app->menu);
1093 g_value_array_append(values, &value);
1094 g_value_unset(&value);
1095
1096 /* Icon path */
1097 g_value_init(&value, G_TYPE_STRING);
1098 g_value_set_string(&value, app->icon_theme_path);
1099 g_value_array_append(values, &value);
1100 g_value_unset(&value);
1101
1102 /* Label */
1103 g_value_init(&value, G_TYPE_STRING);
1104 g_value_set_string(&value, app->label);
1105 g_value_array_append(values, &value);
1106 g_value_unset(&value);
1107
1108 /* Guide */
1109 g_value_init(&value, G_TYPE_STRING);
1110 g_value_set_string(&value, app->guide);
1111 g_value_array_append(values, &value);
1112 g_value_unset(&value);
1113
1114 g_ptr_array_add(*apps, values);
1115 }
1116
1117 return TRUE;
1118}
1119
1120/* Removes and approver from our list of approvers and
1121 then sees if that changes our status. Most likely this
1122 could make us visible if this approver rejected us. */
1123static void
1124remove_approver (gpointer papp, gpointer pproxy)
1125{
1126 Application * app = (Application *)papp;
1127 app->approved_by = g_list_remove(app->approved_by, pproxy);
1128 apply_status(app);
1129 return;
1130}
1131
1132/* Frees the data associated with an approver */
1133static void
1134approver_free (gpointer papprover, gpointer user_data)
1135{
1136 Approver * approver = (Approver *)papprover;
1137 g_return_if_fail(approver != NULL);
1138
1139 ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(user_data);
1140 g_list_foreach(appstore->priv->applications, remove_approver, approver->proxy);
1141
1142 if (approver->proxy != NULL) {
1143 if (!approver->destroy_by_proxy) {
1144 g_object_unref(approver->proxy);
1145 }
1146 approver->proxy = NULL;
1147 }
1148
1149 g_free(approver);
1150 return;
1151}
1152
1153/* What did the approver tell us? */
1154static void
1155approver_request_cb (DBusGProxy *proxy, gboolean OUT_approved, GError *error, gpointer userdata)
1156{
1157 if (error == NULL) {
1158 g_debug("Approver responded: %s", OUT_approved ? "approve" : "rejected");
1159 } else {
1160 g_debug("Approver responded error: %s", error->message);
1161 }
1162
1163 Application * app = (Application *)userdata;
1164
1165 if (OUT_approved || error != NULL) {
1166 app->approved_by = g_list_prepend(app->approved_by, proxy);
1167 } else {
1168 app->approved_by = g_list_remove(app->approved_by, proxy);
1169 }
1170
1171 apply_status(app);
1172 return;
1173}
1174
1175/* Run the applications through the new approver */
1176static void
1177check_with_new_approver (gpointer papp, gpointer papprove)
1178{
1179 Application * app = (Application *)papp;
1180 Approver * approver = (Approver *)papprove;
1181
1182 org_ayatana_StatusNotifierApprover_approve_item_async(approver->proxy,
1183 app->id,
1184 app->category,
1185 0,
1186 app->dbus_name,
1187 app->dbus_object,
1188 approver_request_cb,
1189 app);
1190
1191 return;
1192}
1193
1194/* Look through all the approvers and find the one with a given
1195 proxy. */
1196static gint
1197approver_find_by_proxy (gconstpointer papprover, gconstpointer pproxy)
1198{
1199 Approver * approver = (Approver *)papprover;
1200
1201 if (approver->proxy == pproxy) {
1202 return 0;
1203 }
1204
1205 return -1;
1206}
1207
1208/* Tracks when a proxy gets destroyed so that we know that the
1209 approver has dropped off the bus. */
1210static void
1211approver_destroyed (gpointer pproxy, gpointer pappstore)
1212{
1213 ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(pappstore);
1214
1215 GList * lapprover = g_list_find_custom(appstore->priv->approvers, pproxy, approver_find_by_proxy);
1216 if (lapprover == NULL) {
1217 g_warning("Approver proxy died, but we don't seem to have that approver.");
1218 return;
1219 }
1220
1221 Approver * approver = (Approver *)lapprover->data;
1222 approver->destroy_by_proxy = TRUE;
1223
1224 appstore->priv->approvers = g_list_remove(appstore->priv->approvers, approver);
1225 approver_free(approver, appstore);
1226
1227 return;
1228}
1229
1230/* A signal when an approver changes the why that it thinks about
1231 a particular indicator. */
1232void
1233approver_revise_judgement (DBusGProxy * proxy, gboolean new_status, gchar * address, DBusGProxy * get_path, gpointer user_data)
1234{
1235 g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(user_data));
1236 g_return_if_fail(address != NULL && address[0] != '\0');
1237 g_return_if_fail(get_path != NULL);
1238 const gchar * path = dbus_g_proxy_get_path(get_path);
1239 g_return_if_fail(path != NULL && path[0] != '\0');
1240
1241 ApplicationServiceAppstore * appstore = APPLICATION_SERVICE_APPSTORE(user_data);
1242
1243 Application * app = find_application(appstore, address, path);
1244
1245 if (app == NULL) {
1246 g_warning("Unable to update approver status of application (%s:%s) as it was not found", address, path);
1247 return;
1248 }
1249
1250 if (new_status) {
1251 app->approved_by = g_list_prepend(app->approved_by, proxy);
1252 } else {
1253 app->approved_by = g_list_remove(app->approved_by, proxy);
1254 }
1255 apply_status(app);
1256
1257 return;
1258}
1259
1260/* Adds a new approver to the app store */
1261void
1262application_service_appstore_approver_add (ApplicationServiceAppstore * appstore, const gchar * dbus_name, const gchar * dbus_object)
1263{
1264 g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(appstore));
1265 g_return_if_fail(dbus_name != NULL);
1266 g_return_if_fail(dbus_object != NULL);
1267 ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (appstore);
1268
1269 Approver * approver = g_new0(Approver, 1);
1270 approver->destroy_by_proxy = FALSE;
1271
1272 GError * error = NULL;
1273 approver->proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1274 dbus_name,
1275 dbus_object,
1276 NOTIFICATION_APPROVER_DBUS_IFACE,
1277 &error);
1278 if (error != NULL) {
1279 g_warning("Unable to get approver interface on '%s:%s' : %s", dbus_name, dbus_object, error->message);
1280 g_error_free(error);
1281 g_free(approver);
1282 return;
1283 }
1284
1285 g_signal_connect(G_OBJECT(approver->proxy), "destroy", G_CALLBACK(approver_destroyed), appstore);
1286
1287 dbus_g_proxy_add_signal(approver->proxy,
1288 "ReviseJudgement",
1289 G_TYPE_BOOLEAN,
1290 G_TYPE_STRING,
1291 DBUS_TYPE_G_OBJECT_PATH,
1292 G_TYPE_INVALID);
1293 dbus_g_proxy_connect_signal(approver->proxy,
1294 "ReviseJudgement",
1295 G_CALLBACK(approver_revise_judgement),
1296 appstore,
1297 NULL);
1298
1299 priv->approvers = g_list_prepend(priv->approvers, approver);
1300
1301 g_list_foreach(priv->applications, check_with_new_approver, approver);
1302
1303 return;
1304}
1305
13060
=== removed file 'src/application-service-appstore.h'
--- src/application-service-appstore.h 2010-10-08 15:02:24 +0000
+++ src/application-service-appstore.h 1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
1/*
2An object that stores the registration of all the application
3indicators. It also communicates this to the indicator visualization.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifndef __APPLICATION_SERVICE_APPSTORE_H__
24#define __APPLICATION_SERVICE_APPSTORE_H__
25
26#include <glib.h>
27#include <glib-object.h>
28
29G_BEGIN_DECLS
30
31#define APPLICATION_SERVICE_APPSTORE_TYPE (application_service_appstore_get_type ())
32#define APPLICATION_SERVICE_APPSTORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APPLICATION_SERVICE_APPSTORE_TYPE, ApplicationServiceAppstore))
33#define APPLICATION_SERVICE_APPSTORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APPLICATION_SERVICE_APPSTORE_TYPE, ApplicationServiceAppstoreClass))
34#define IS_APPLICATION_SERVICE_APPSTORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APPLICATION_SERVICE_APPSTORE_TYPE))
35#define IS_APPLICATION_SERVICE_APPSTORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APPLICATION_SERVICE_APPSTORE_TYPE))
36#define APPLICATION_SERVICE_APPSTORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APPLICATION_SERVICE_APPSTORE_TYPE, ApplicationServiceAppstoreClass))
37
38typedef struct _ApplicationServiceAppstore ApplicationServiceAppstore;
39typedef struct _ApplicationServiceAppstoreClass ApplicationServiceAppstoreClass;
40typedef struct _ApplicationServiceAppstorePrivate ApplicationServiceAppstorePrivate;
41
42struct _ApplicationServiceAppstoreClass {
43 GObjectClass parent_class;
44
45 void (*application_added) (ApplicationServiceAppstore * appstore, gchar *, gint, gchar *, gchar *, gpointer);
46 void (*application_removed) (ApplicationServiceAppstore * appstore, gint, gpointer);
47 void (*application_icon_changed)(ApplicationServiceAppstore * appstore, gint, const gchar *, gpointer);
48 void (*application_icon_theme_path_changed)(ApplicationServiceAppstore * appstore, gint, const gchar *, gpointer);
49 void (*application_label_changed)(ApplicationServiceAppstore * appstore, gint, const gchar *, const gchar *, gpointer);
50};
51
52struct _ApplicationServiceAppstore {
53 GObject parent;
54
55 ApplicationServiceAppstorePrivate * priv;
56};
57
58ApplicationServiceAppstore * application_service_appstore_new (void);
59GType application_service_appstore_get_type (void);
60void application_service_appstore_application_add (ApplicationServiceAppstore * appstore,
61 const gchar * dbus_name,
62 const gchar * dbus_object);
63void application_service_appstore_application_remove (ApplicationServiceAppstore * appstore,
64 const gchar * dbus_name,
65 const gchar * dbus_object);
66void application_service_appstore_approver_add (ApplicationServiceAppstore * appstore,
67 const gchar * dbus_name,
68 const gchar * dbus_object);
69gchar** application_service_appstore_application_get_list (ApplicationServiceAppstore * appstore);
70
71G_END_DECLS
72
73#endif
740
=== removed file 'src/application-service-watcher.c'
--- src/application-service-watcher.c 2010-10-08 16:04:27 +0000
+++ src/application-service-watcher.c 1970-01-01 00:00:00 +0000
@@ -1,302 +0,0 @@
1/*
2An object implementing the NotificationWatcher interface and passes
3the information into the app-store.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <dbus/dbus-glib.h>
28#include <dbus/dbus-glib-lowlevel.h>
29#include <dbus/dbus-glib-bindings.h>
30#include "application-service-watcher.h"
31#include "dbus-shared.h"
32
33/* Enum for the properties so that they can be quickly
34 found and looked up. */
35enum {
36 PROP_0,
37 PROP_PROTOCOL_VERSION,
38 PROP_IS_STATUS_NOTIFIER_HOST_REGISTERED,
39 PROP_REGISTERED_STATUS_NOTIFIER_ITEMS
40};
41
42/* The strings so that they can be slowly looked up. */
43#define PROP_PROTOCOL_VERSION_S "protocol-version"
44#define PROP_IS_STATUS_NOTIFIER_HOST_REGISTERED_S "is-status-notifier-host-registered"
45#define PROP_REGISTERED_STATUS_NOTIFIER_ITEMS_S "registered-status-notifier-items"
46
47#define CURRENT_PROTOCOL_VERSION 0
48
49static gboolean _notification_watcher_server_register_status_notifier_item (ApplicationServiceWatcher * appwatcher, const gchar * service, DBusGMethodInvocation * method);
50static gboolean _notification_watcher_server_register_status_notifier_host (ApplicationServiceWatcher * appwatcher, const gchar * host);
51static gboolean _notification_watcher_server_x_ayatana_register_notification_approver (ApplicationServiceWatcher * appwatcher, const gchar * path, const GArray * categories, DBusGMethodInvocation * method);
52static void get_name_cb (DBusGProxy * proxy, guint status, GError * error, gpointer data);
53
54#include "notification-watcher-server.h"
55
56/* Private Stuff */
57typedef struct _ApplicationServiceWatcherPrivate ApplicationServiceWatcherPrivate;
58struct _ApplicationServiceWatcherPrivate {
59 ApplicationServiceAppstore * appstore;
60 DBusGProxy * dbus_proxy;
61};
62
63#define APPLICATION_SERVICE_WATCHER_GET_PRIVATE(o) \
64(G_TYPE_INSTANCE_GET_PRIVATE ((o), APPLICATION_SERVICE_WATCHER_TYPE, ApplicationServiceWatcherPrivate))
65
66/* Signals Stuff */
67enum {
68 STATUS_NOTIFIER_ITEM_REGISTERED,
69 STATUS_NOTIFIER_ITEM_UNREGISTERED,
70 STATUS_NOTIFIER_HOST_REGISTERED,
71 LAST_SIGNAL
72};
73
74static guint signals[LAST_SIGNAL] = { 0 };
75
76/* GObject stuff */
77static void application_service_watcher_class_init (ApplicationServiceWatcherClass *klass);
78static void application_service_watcher_init (ApplicationServiceWatcher *self);
79static void application_service_watcher_dispose (GObject *object);
80static void application_service_watcher_finalize (GObject *object);
81static void application_service_watcher_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
82static void application_service_watcher_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
83
84G_DEFINE_TYPE (ApplicationServiceWatcher, application_service_watcher, G_TYPE_OBJECT);
85
86static void
87application_service_watcher_class_init (ApplicationServiceWatcherClass *klass)
88{
89 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90
91 g_type_class_add_private (klass, sizeof (ApplicationServiceWatcherPrivate));
92
93 object_class->dispose = application_service_watcher_dispose;
94 object_class->finalize = application_service_watcher_finalize;
95
96 /* Property funcs */
97 object_class->set_property = application_service_watcher_set_property;
98 object_class->get_property = application_service_watcher_get_property;
99
100 /* Properties */
101 g_object_class_install_property (object_class,
102 PROP_PROTOCOL_VERSION,
103 g_param_spec_int(PROP_PROTOCOL_VERSION_S,
104 "Protocol Version",
105 "Which version of the StatusNotifierProtocol this watcher implements",
106 0, G_MAXINT,
107 CURRENT_PROTOCOL_VERSION,
108 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
109 g_object_class_install_property (object_class,
110 PROP_IS_STATUS_NOTIFIER_HOST_REGISTERED,
111 g_param_spec_boolean(PROP_IS_STATUS_NOTIFIER_HOST_REGISTERED_S,
112 "Is StatusNotifierHost Registered",
113 "True if there is at least one StatusNotifierHost registered",
114 FALSE,
115 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
116 g_object_class_install_property (object_class,
117 PROP_REGISTERED_STATUS_NOTIFIER_ITEMS,
118 g_param_spec_boxed(PROP_REGISTERED_STATUS_NOTIFIER_ITEMS_S,
119 "Registered StatusNotifierItems",
120 "The list of StatusNotifierItems registered to this watcher",
121 G_TYPE_STRV,
122 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
123 /* Signals */
124 signals[STATUS_NOTIFIER_ITEM_REGISTERED] = g_signal_new ("status-notifier-item-registered",
125 G_TYPE_FROM_CLASS(klass),
126 G_SIGNAL_RUN_LAST,
127 G_STRUCT_OFFSET (ApplicationServiceWatcherClass, status_notifier_item_registered),
128 NULL, NULL,
129 g_cclosure_marshal_VOID__STRING,
130 G_TYPE_NONE, 1, G_TYPE_STRING, G_TYPE_NONE);
131 signals[STATUS_NOTIFIER_ITEM_UNREGISTERED] = g_signal_new ("status-notifier-item-unregistered",
132 G_TYPE_FROM_CLASS(klass),
133 G_SIGNAL_RUN_LAST,
134 G_STRUCT_OFFSET (ApplicationServiceWatcherClass, status_notifier_item_unregistered),
135 NULL, NULL,
136 g_cclosure_marshal_VOID__STRING,
137 G_TYPE_NONE, 1, G_TYPE_STRING, G_TYPE_NONE);
138 signals[STATUS_NOTIFIER_HOST_REGISTERED] = g_signal_new ("status-notifier-host-registered",
139 G_TYPE_FROM_CLASS(klass),
140 G_SIGNAL_RUN_LAST,
141 G_STRUCT_OFFSET (ApplicationServiceWatcherClass, status_notifier_host_registered),
142 NULL, NULL,
143 g_cclosure_marshal_VOID__VOID,
144 G_TYPE_NONE, 0, G_TYPE_NONE);
145
146 dbus_g_object_type_install_info(APPLICATION_SERVICE_WATCHER_TYPE,
147 &dbus_glib__notification_watcher_server_object_info);
148
149 return;
150}
151
152static void
153application_service_watcher_init (ApplicationServiceWatcher *self)
154{
155 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(self);
156
157 priv->appstore = NULL;
158
159 GError * error = NULL;
160 DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
161 if (error != NULL) {
162 g_error("Unable to get session bus: %s", error->message);
163 g_error_free(error);
164 return;
165 }
166
167 dbus_g_connection_register_g_object(session_bus,
168 NOTIFICATION_WATCHER_DBUS_OBJ,
169 G_OBJECT(self));
170
171 priv->dbus_proxy = dbus_g_proxy_new_for_name_owner(session_bus,
172 DBUS_SERVICE_DBUS,
173 DBUS_PATH_DBUS,
174 DBUS_INTERFACE_DBUS,
175 &error);
176 if (error != NULL) {
177 g_error("Ah, can't get proxy to dbus: %s", error->message);
178 g_error_free(error);
179 return;
180 }
181
182 org_freedesktop_DBus_request_name_async(priv->dbus_proxy,
183 NOTIFICATION_WATCHER_DBUS_ADDR,
184 DBUS_NAME_FLAG_DO_NOT_QUEUE,
185 get_name_cb,
186 self);
187
188 return;
189}
190
191static void
192application_service_watcher_dispose (GObject *object)
193{
194 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(object);
195
196 if (priv->appstore != NULL) {
197 g_object_unref(G_OBJECT(priv->appstore));
198 priv->appstore = NULL;
199 }
200
201 G_OBJECT_CLASS (application_service_watcher_parent_class)->dispose (object);
202 return;
203}
204
205static void
206application_service_watcher_finalize (GObject *object)
207{
208
209 G_OBJECT_CLASS (application_service_watcher_parent_class)->finalize (object);
210 return;
211}
212
213static void
214application_service_watcher_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
215{
216 /* There are no writable properties for now */
217}
218
219static void
220application_service_watcher_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
221{
222 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(object);
223 switch (prop_id) {
224 case PROP_PROTOCOL_VERSION:
225 g_value_set_int (value, CURRENT_PROTOCOL_VERSION);
226 break;
227 case PROP_IS_STATUS_NOTIFIER_HOST_REGISTERED:
228 g_value_set_boolean (value, TRUE);
229 break;
230 case PROP_REGISTERED_STATUS_NOTIFIER_ITEMS:
231 g_value_set_boxed (value, application_service_appstore_application_get_list(priv->appstore));
232 break;
233 }
234}
235
236ApplicationServiceWatcher *
237application_service_watcher_new (ApplicationServiceAppstore * appstore)
238{
239 GObject * obj = g_object_new(APPLICATION_SERVICE_WATCHER_TYPE, NULL);
240 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(obj);
241 priv->appstore = appstore;
242 g_object_ref(G_OBJECT(priv->appstore));
243 return APPLICATION_SERVICE_WATCHER(obj);
244}
245
246static gboolean
247_notification_watcher_server_register_status_notifier_item (ApplicationServiceWatcher * appwatcher, const gchar * service, DBusGMethodInvocation * method)
248{
249 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(appwatcher);
250
251 if (service[0] == '/') {
252 application_service_appstore_application_add(priv->appstore,
253 dbus_g_method_get_sender(method),
254 service);
255 } else {
256 application_service_appstore_application_add(priv->appstore,
257 service,
258 NOTIFICATION_ITEM_DEFAULT_OBJ);
259 }
260
261 dbus_g_method_return(method, G_TYPE_NONE);
262 return TRUE;
263}
264
265static gboolean
266_notification_watcher_server_register_status_notifier_host (ApplicationServiceWatcher * appwatcher, const gchar * host)
267{
268
269 return FALSE;
270}
271
272/* Function to handle the return of the get name. There isn't a whole
273 lot that can be done, but we're atleast going to tell people. */
274static void
275get_name_cb (DBusGProxy * proxy, guint status, GError * error, gpointer data)
276{
277 if (error != NULL) {
278 g_warning("Unable to get watcher name '%s' because: %s", NOTIFICATION_WATCHER_DBUS_ADDR, error->message);
279 return;
280 }
281
282 if (status != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER &&
283 status != DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER) {
284 g_warning("Unable to get watcher name '%s'", NOTIFICATION_WATCHER_DBUS_ADDR);
285 return;
286 }
287
288 return;
289}
290
291static gboolean
292_notification_watcher_server_x_ayatana_register_notification_approver (ApplicationServiceWatcher * appwatcher, const gchar * path, const GArray * categories, DBusGMethodInvocation * method)
293{
294 ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(appwatcher);
295
296 application_service_appstore_approver_add(priv->appstore,
297 dbus_g_method_get_sender(method),
298 path);
299
300 dbus_g_method_return(method, G_TYPE_NONE);
301 return TRUE;
302}
3030
=== removed file 'src/application-service-watcher.h'
--- src/application-service-watcher.h 2010-10-08 16:04:27 +0000
+++ src/application-service-watcher.h 1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
1/*
2An object implementing the NotificationWatcher interface and passes
3the information into the app-store.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifndef __APPLICATION_SERVICE_WATCHER_H__
24#define __APPLICATION_SERVICE_WATCHER_H__
25
26#include <glib.h>
27#include <glib-object.h>
28
29#include "application-service-appstore.h"
30
31G_BEGIN_DECLS
32
33#define APPLICATION_SERVICE_WATCHER_TYPE (application_service_watcher_get_type ())
34#define APPLICATION_SERVICE_WATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APPLICATION_SERVICE_WATCHER_TYPE, ApplicationServiceWatcher))
35#define APPLICATION_SERVICE_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APPLICATION_SERVICE_WATCHER_TYPE, ApplicationServiceWatcherClass))
36#define IS_APPLICATION_SERVICE_WATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APPLICATION_SERVICE_WATCHER_TYPE))
37#define IS_APPLICATION_SERVICE_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APPLICATION_SERVICE_WATCHER_TYPE))
38#define APPLICATION_SERVICE_WATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APPLICATION_SERVICE_WATCHER_TYPE, ApplicationServiceWatcherClass))
39
40typedef struct _ApplicationServiceWatcher ApplicationServiceWatcher;
41typedef struct _ApplicationServiceWatcherClass ApplicationServiceWatcherClass;
42
43struct _ApplicationServiceWatcherClass {
44 GObjectClass parent_class;
45
46 /* Signals */
47 void (*status_notifier_item_registered) (ApplicationServiceWatcher * watcher, gchar * object, gpointer data);
48 void (*status_notifier_item_unregistered) (ApplicationServiceWatcher * watcher, gchar * object, gpointer data);
49 void (*status_notifier_host_registered) (ApplicationServiceWatcher * watcher, gpointer data);
50};
51
52struct _ApplicationServiceWatcher {
53 GObject parent;
54};
55
56GType application_service_watcher_get_type (void);
57ApplicationServiceWatcher * application_service_watcher_new (ApplicationServiceAppstore * appstore);
58
59G_END_DECLS
60
61#endif
620
=== removed file 'src/application-service.c'
--- src/application-service.c 2010-08-10 19:47:23 +0000
+++ src/application-service.c 1970-01-01 00:00:00 +0000
@@ -1,78 +0,0 @@
1/*
2The core file for the service that starts up all the objects we need
3and houses our main loop.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23
24#include "libindicator/indicator-service.h"
25#include "notification-item-client.h"
26#include "application-service-appstore.h"
27#include "application-service-watcher.h"
28#include "dbus-shared.h"
29
30/* The base main loop */
31static GMainLoop * mainloop = NULL;
32/* Where the application registry lives */
33static ApplicationServiceAppstore * appstore = NULL;
34/* Interface for applications */
35static ApplicationServiceWatcher * watcher = NULL;
36/* The service management interface */
37static IndicatorService * service = NULL;
38
39/* Recieves the disonnection signal from the service
40 object and closes the mainloop. */
41static void
42service_disconnected (IndicatorService * service, gpointer data)
43{
44 g_debug("Service disconnected");
45 if (mainloop != NULL) {
46 g_main_loop_quit(mainloop);
47 }
48 return;
49}
50
51/* Builds up the core objects and puts us spinning into
52 a main loop. */
53int
54main (int argc, char ** argv)
55{
56 g_type_init();
57
58 /* Bring us up as a basic indicator service */
59 service = indicator_service_new(INDICATOR_APPLICATION_DBUS_ADDR);
60 g_signal_connect(G_OBJECT(service), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_disconnected), NULL);
61
62 /* Building our app store */
63 appstore = application_service_appstore_new();
64
65 /* Adding a watcher for the Apps coming up */
66 watcher = application_service_watcher_new(appstore);
67
68 /* Building and executing our main loop */
69 mainloop = g_main_loop_new(NULL, FALSE);
70 g_main_loop_run(mainloop);
71
72 /* Unref'ing all the objects */
73 g_object_unref(G_OBJECT(watcher));
74 g_object_unref(G_OBJECT(appstore));
75 g_object_unref(G_OBJECT(service));
76
77 return 0;
78}
790
=== removed file 'src/application-service.xml'
--- src/application-service.xml 2010-08-05 21:54:12 +0000
+++ src/application-service.xml 1970-01-01 00:00:00 +0000
@@ -1,59 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3An interface for communication between the service and indicator.
4
5Copyright 2009 Canonical Ltd.
6
7Authors:
8 Ted Gould <ted@canonical.com>
9
10This program is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License version 3, as published
12by the Free Software Foundation.
13
14This program is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranties of
16MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along
20with this program. If not, see <http://www.gnu.org/licenses/>.
21-->
22<node name="/">
23 <interface name="org.ayatana.indicator.application.service">
24<!-- Properties -->
25 <!-- None currently -->
26
27<!-- Methods -->
28 <method name="GetApplications">
29 <arg type="a(sisosss)" name="applications" direction="out" />
30 </method>
31
32<!-- Signals -->
33 <signal name="ApplicationAdded">
34 <arg type="s" name="iconname" direction="out" />
35 <arg type="i" name="position" direction="out" />
36 <arg type="s" name="dbusaddress" direction="out" />
37 <arg type="o" name="dbusobject" direction="out" />
38 <arg type="s" name="iconpath" direction="out" />
39 <arg type="s" name="label" direction="out" />
40 <arg type="s" name="labelguide" direction="out" />
41 </signal>
42 <signal name="ApplicationRemoved">
43 <arg type="i" name="position" direction="out" />
44 </signal>
45 <signal name="ApplicationIconChanged">
46 <arg type="i" name="position" direction="out" />
47 <arg type="s" name="icon_name" direction="out" />
48 </signal>
49 <signal name="ApplicationIconThemePathChanged">
50 <arg type="i" name="position" direction="out" />
51 <arg type="s" name="icon_theme_path" direction="out" />
52 </signal>
53 <signal name="ApplicationLabelChanged">
54 <arg type="i" name="position" direction="out" />
55 <arg type="s" name="label" direction="out" />
56 <arg type="s" name="guide" direction="out" />
57 </signal>
58 </interface>
59</node>
600
=== removed file 'src/dbus-properties.xml'
--- src/dbus-properties.xml 2009-11-07 04:50:48 +0000
+++ src/dbus-properties.xml 1970-01-01 00:00:00 +0000
@@ -1,23 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<node name="/">
3 <interface name="org.freedesktop.DBus.Properties">
4
5 <method name="Get">
6 <arg direction="in" type="s" name="Interface_Name"/>
7 <arg direction="in" type="s" name="Property_Name"/>
8 <arg direction="out" type="v" name="Value"/>
9 </method>
10
11 <method name="Set">
12 <arg direction="in" type="s" name="Interface_Name"/>
13 <arg direction="in" type="s" name="Property_Name"/>
14 <arg direction="in" type="v" name="Value"/>
15 </method>
16
17 <method name="GetAll">
18 <arg direction="in" type="s" name="Interface_Name"/>
19 <arg direction="out" type="a{sv}" name="Properties"/>
20 </method>
21
22 </interface>
23</node>
240
=== removed file 'src/indicator-application.c'
--- src/indicator-application.c 2010-12-04 03:12:06 +0000
+++ src/indicator-application.c 1970-01-01 00:00:00 +0000
@@ -1,879 +0,0 @@
1/*
2The indicator application visualization object. It takes the information
3given by the service and turns it into real-world pixels that users can
4actually use. Well, GTK does that, but this asks nicely.
5
6Copyright 2009 Canonical Ltd.
7
8Authors:
9 Ted Gould <ted@canonical.com>
10
11This program is free software: you can redistribute it and/or modify it
12under the terms of the GNU General Public License version 3, as published
13by the Free Software Foundation.
14
15This program is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranties of
17MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
18PURPOSE. See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License along
21with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28/* G Stuff */
29#include <glib.h>
30#include <glib-object.h>
31#include <gtk/gtk.h>
32
33/* DBus Stuff */
34#include <dbus/dbus-glib.h>
35#ifdef HAVE_GTK3
36#include <libdbusmenu-gtk3/menu.h>
37#else
38#include <libdbusmenu-gtk/menu.h>
39#endif
40
41/* Indicator Stuff */
42#include <libindicator/indicator.h>
43#include <libindicator/indicator-object.h>
44#include <libindicator/indicator-service-manager.h>
45#include <libindicator/indicator-image-helper.h>
46
47/* Local Stuff */
48#include "dbus-shared.h"
49#include "application-service-client.h"
50#include "application-service-marshal.h"
51
52#define PANEL_ICON_SUFFIX "panel"
53
54#define INDICATOR_APPLICATION_TYPE (indicator_application_get_type ())
55#define INDICATOR_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_APPLICATION_TYPE, IndicatorApplication))
56#define INDICATOR_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_APPLICATION_TYPE, IndicatorApplicationClass))
57#define IS_INDICATOR_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_APPLICATION_TYPE))
58#define IS_INDICATOR_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_APPLICATION_TYPE))
59#define INDICATOR_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_APPLICATION_TYPE, IndicatorApplicationClass))
60
61typedef struct _IndicatorApplication IndicatorApplication;
62typedef struct _IndicatorApplicationClass IndicatorApplicationClass;
63
64struct _IndicatorApplicationClass {
65 IndicatorObjectClass parent_class;
66};
67
68struct _IndicatorApplication {
69 IndicatorObject parent;
70};
71
72GType indicator_application_get_type (void);
73
74INDICATOR_SET_VERSION
75INDICATOR_SET_TYPE(INDICATOR_APPLICATION_TYPE)
76
77#ifdef HAVE_CONFIG_H
78#include "config.h"
79#endif
80
81typedef struct _IndicatorApplicationPrivate IndicatorApplicationPrivate;
82struct _IndicatorApplicationPrivate {
83 IndicatorServiceManager * sm;
84 DBusGConnection * bus;
85 DBusGProxy * service_proxy;
86 GList * applications;
87 GHashTable * theme_dirs;
88 guint disconnect_kill;
89};
90
91typedef struct _ApplicationEntry ApplicationEntry;
92struct _ApplicationEntry {
93 IndicatorObjectEntry entry;
94 gchar * icon_theme_path;
95 gboolean old_service;
96 gchar * dbusobject;
97 gchar * dbusaddress;
98 gchar * guide;
99 gchar * longname;
100};
101
102#define INDICATOR_APPLICATION_GET_PRIVATE(o) \
103(G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_APPLICATION_TYPE, IndicatorApplicationPrivate))
104
105static void indicator_application_class_init (IndicatorApplicationClass *klass);
106static void indicator_application_init (IndicatorApplication *self);
107static void indicator_application_dispose (GObject *object);
108static void indicator_application_finalize (GObject *object);
109static GList * get_entries (IndicatorObject * io);
110static guint get_location (IndicatorObject * io, IndicatorObjectEntry * entry);
111void connection_changed (IndicatorServiceManager * sm, gboolean connected, IndicatorApplication * application);
112static void connected (IndicatorApplication * application);
113static void disconnected (IndicatorApplication * application);
114static void disconnected_helper (gpointer data, gpointer user_data);
115static gboolean disconnected_kill (gpointer user_data);
116static void disconnected_kill_helper (gpointer data, gpointer user_data);
117static void application_added (DBusGProxy * proxy, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide, IndicatorApplication * application);
118static void application_removed (DBusGProxy * proxy, gint position , IndicatorApplication * application);
119static void application_label_changed (DBusGProxy * proxy, gint position, const gchar * label, const gchar * guide, IndicatorApplication * application);
120static void application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application);
121static void application_icon_theme_path_changed (DBusGProxy * proxy, gint position, const gchar * icon_theme_path, IndicatorApplication * application);
122static void get_applications (DBusGProxy *proxy, GPtrArray *OUT_applications, GError *error, gpointer userdata);
123static void get_applications_helper (gpointer data, gpointer user_data);
124static void theme_dir_unref(IndicatorApplication * ia, const gchar * dir);
125static void theme_dir_ref(IndicatorApplication * ia, const gchar * dir);
126
127G_DEFINE_TYPE (IndicatorApplication, indicator_application, INDICATOR_OBJECT_TYPE);
128
129static void
130indicator_application_class_init (IndicatorApplicationClass *klass)
131{
132 GObjectClass *object_class = G_OBJECT_CLASS (klass);
133
134 g_type_class_add_private (klass, sizeof (IndicatorApplicationPrivate));
135
136 object_class->dispose = indicator_application_dispose;
137 object_class->finalize = indicator_application_finalize;
138
139 IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
140
141 io_class->get_entries = get_entries;
142 io_class->get_location = get_location;
143
144 dbus_g_object_register_marshaller(_application_service_marshal_VOID__STRING_INT_STRING_STRING_STRING_STRING_STRING,
145 G_TYPE_NONE,
146 G_TYPE_STRING,
147 G_TYPE_INT,
148 G_TYPE_STRING,
149 G_TYPE_STRING,
150 G_TYPE_STRING,
151 G_TYPE_STRING,
152 G_TYPE_STRING,
153 G_TYPE_INVALID);
154 dbus_g_object_register_marshaller(_application_service_marshal_VOID__INT_STRING,
155 G_TYPE_NONE,
156 G_TYPE_INT,
157 G_TYPE_STRING,
158 G_TYPE_INVALID);
159 dbus_g_object_register_marshaller(_application_service_marshal_VOID__INT_STRING_STRING,
160 G_TYPE_NONE,
161 G_TYPE_INT,
162 G_TYPE_STRING,
163 G_TYPE_STRING,
164 G_TYPE_INVALID);
165
166 return;
167}
168
169static void
170indicator_application_init (IndicatorApplication *self)
171{
172 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(self);
173
174 /* These are built in the connection phase */
175 priv->bus = NULL;
176 priv->service_proxy = NULL;
177 priv->theme_dirs = NULL;
178 priv->disconnect_kill = 0;
179
180 priv->sm = indicator_service_manager_new(INDICATOR_APPLICATION_DBUS_ADDR);
181 g_signal_connect(G_OBJECT(priv->sm), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_changed), self);
182
183 priv->applications = NULL;
184
185 priv->theme_dirs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
186
187 return;
188}
189
190static void
191indicator_application_dispose (GObject *object)
192{
193 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(object);
194
195 if (priv->disconnect_kill != 0) {
196 g_source_remove(priv->disconnect_kill);
197 }
198
199 while (priv->applications != NULL) {
200 application_removed(priv->service_proxy,
201 0,
202 INDICATOR_APPLICATION(object));
203 }
204
205 if (priv->sm != NULL) {
206 g_object_unref(priv->sm);
207 priv->sm = NULL;
208 }
209
210 if (priv->bus != NULL) {
211 /* We're not incrementing the ref count on this one. */
212 priv->bus = NULL;
213 }
214
215 if (priv->service_proxy != NULL) {
216 g_object_unref(G_OBJECT(priv->service_proxy));
217 priv->service_proxy = NULL;
218 }
219
220 if (priv->theme_dirs != NULL) {
221 while (g_hash_table_size(priv->theme_dirs)) {
222 GList * keys = g_hash_table_get_keys(priv->theme_dirs);
223 theme_dir_unref(INDICATOR_APPLICATION(object), (gchar *)keys->data);
224 }
225 g_hash_table_destroy(priv->theme_dirs);
226 priv->theme_dirs = NULL;
227 }
228
229 G_OBJECT_CLASS (indicator_application_parent_class)->dispose (object);
230 return;
231}
232
233static void
234indicator_application_finalize (GObject *object)
235{
236
237 G_OBJECT_CLASS (indicator_application_parent_class)->finalize (object);
238 return;
239}
240
241/* Responds to connection change event from the service manager and
242 splits it into two. */
243void
244connection_changed (IndicatorServiceManager * sm, gboolean connect, IndicatorApplication * application)
245{
246 g_return_if_fail(IS_INDICATOR_APPLICATION(application));
247 if (connect) {
248 connected(application);
249 } else {
250 disconnected(application);
251 }
252 return;
253}
254
255/* Brings up the connection to a service that has just come onto the
256 bus, or is atleast new to us. */
257void
258connected (IndicatorApplication * application)
259{
260 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
261 g_debug("Connected to Application Indicator Service.");
262
263 GError * error = NULL;
264
265 /* Grab the session bus */
266 if (priv->bus == NULL) {
267 priv->bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
268
269 if (error != NULL) {
270 g_error("Unable to get session bus: %s", error->message);
271 g_error_free(error);
272 return;
273 }
274 }
275
276 if (priv->service_proxy == NULL) {
277 /* Build the service proxy */
278 priv->service_proxy = dbus_g_proxy_new_for_name(priv->bus,
279 INDICATOR_APPLICATION_DBUS_ADDR,
280 INDICATOR_APPLICATION_DBUS_OBJ,
281 INDICATOR_APPLICATION_DBUS_IFACE);
282
283 /* Set up proxy signals */
284 g_debug("Setup proxy signals");
285 dbus_g_proxy_add_signal(priv->service_proxy,
286 "ApplicationAdded",
287 G_TYPE_STRING,
288 G_TYPE_INT,
289 G_TYPE_STRING,
290 G_TYPE_STRING,
291 G_TYPE_STRING,
292 G_TYPE_STRING,
293 G_TYPE_STRING,
294 G_TYPE_INVALID);
295 dbus_g_proxy_add_signal(priv->service_proxy,
296 "ApplicationRemoved",
297 G_TYPE_INT,
298 G_TYPE_INVALID);
299 dbus_g_proxy_add_signal(priv->service_proxy,
300 "ApplicationIconChanged",
301 G_TYPE_INT,
302 G_TYPE_STRING,
303 G_TYPE_INVALID);
304 dbus_g_proxy_add_signal(priv->service_proxy,
305 "ApplicationIconThemePathChanged",
306 G_TYPE_INT,
307 G_TYPE_STRING,
308 G_TYPE_INVALID);
309 dbus_g_proxy_add_signal(priv->service_proxy,
310 "ApplicationLabelChanged",
311 G_TYPE_INT,
312 G_TYPE_STRING,
313 G_TYPE_STRING,
314 G_TYPE_INVALID);
315
316 /* Connect to them */
317 g_debug("Connect to them.");
318 dbus_g_proxy_connect_signal(priv->service_proxy,
319 "ApplicationAdded",
320 G_CALLBACK(application_added),
321 application,
322 NULL /* Disconnection Signal */);
323 dbus_g_proxy_connect_signal(priv->service_proxy,
324 "ApplicationRemoved",
325 G_CALLBACK(application_removed),
326 application,
327 NULL /* Disconnection Signal */);
328 dbus_g_proxy_connect_signal(priv->service_proxy,
329 "ApplicationIconChanged",
330 G_CALLBACK(application_icon_changed),
331 application,
332 NULL /* Disconnection Signal */);
333 dbus_g_proxy_connect_signal(priv->service_proxy,
334 "ApplicationIconThemePathChanged",
335 G_CALLBACK(application_icon_theme_path_changed),
336 application,
337 NULL /* Disconnection Signal */);
338 dbus_g_proxy_connect_signal(priv->service_proxy,
339 "ApplicationLabelChanged",
340 G_CALLBACK(application_label_changed),
341 application,
342 NULL /* Disconnection Signal */);
343 }
344
345 /* Query it for existing applications */
346 g_debug("Request current apps");
347 org_ayatana_indicator_application_service_get_applications_async(priv->service_proxy,
348 get_applications,
349 application);
350
351 return;
352}
353
354/* Marks every current application as belonging to the old
355 service so that we can delete it if it doesn't come back.
356 Also, sets up a timeout on comming back. */
357static void
358disconnected (IndicatorApplication * application)
359{
360 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
361 g_list_foreach(priv->applications, disconnected_helper, application);
362 /* I'll like this to be a little shorter, but it's a bit
363 inpractical to make it so. This means that the user will
364 probably notice a visible glitch. Though, if applications
365 are disappearing there isn't much we can do. */
366 priv->disconnect_kill = g_timeout_add(250, disconnected_kill, application);
367 return;
368}
369
370/* Marks an entry as being from the old service */
371static void
372disconnected_helper (gpointer data, gpointer user_data)
373{
374 ApplicationEntry * entry = (ApplicationEntry *)data;
375 entry->old_service = TRUE;
376 return;
377}
378
379/* Makes sure the old applications that don't come back
380 get dropped. */
381static gboolean
382disconnected_kill (gpointer user_data)
383{
384 g_return_val_if_fail(IS_INDICATOR_APPLICATION(user_data), FALSE);
385 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(user_data);
386 priv->disconnect_kill = 0;
387 g_list_foreach(priv->applications, disconnected_kill_helper, user_data);
388 return FALSE;
389}
390
391/* Looks for entries that are still associated with the
392 old service and removes them. */
393static void
394disconnected_kill_helper (gpointer data, gpointer user_data)
395{
396 g_return_if_fail(IS_INDICATOR_APPLICATION(user_data));
397 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(user_data);
398 ApplicationEntry * entry = (ApplicationEntry *)data;
399 if (entry->old_service) {
400 application_removed(NULL, g_list_index(priv->applications, data), INDICATOR_APPLICATION(user_data));
401 }
402 return;
403}
404
405/* Goes through the list of applications that we're maintaining and
406 pulls out the IndicatorObjectEntry and returns that in a list
407 for the caller. */
408static GList *
409get_entries (IndicatorObject * io)
410{
411 g_return_val_if_fail(IS_INDICATOR_APPLICATION(io), NULL);
412
413 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(io);
414 GList * retval = NULL;
415 GList * apppointer = NULL;
416
417 for (apppointer = priv->applications; apppointer != NULL; apppointer = g_list_next(apppointer)) {
418 IndicatorObjectEntry * entry = &(((ApplicationEntry *)apppointer->data)->entry);
419 retval = g_list_prepend(retval, entry);
420 }
421
422 if (retval != NULL) {
423 retval = g_list_reverse(retval);
424 }
425
426 return retval;
427}
428
429/* Finds the location of a specific entry */
430static guint
431get_location (IndicatorObject * io, IndicatorObjectEntry * entry)
432{
433 g_return_val_if_fail(IS_INDICATOR_APPLICATION(io), 0);
434 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(io);
435 return g_list_index(priv->applications, entry);
436}
437
438/* Searching for ApplicationEntries where the dbusobject and
439 address are the same. */
440static gint
441application_added_search (gconstpointer a, gconstpointer b)
442{
443 ApplicationEntry * appa = (ApplicationEntry *)a;
444 ApplicationEntry * appb = (ApplicationEntry *)b;
445
446 if (g_strcmp0(appa->dbusaddress, appb->dbusaddress) == 0 &&
447 g_strcmp0(appa->dbusobject, appb->dbusobject) == 0) {
448 return 0;
449 }
450
451 return -1;
452}
453
454/* Does a quick meausre of how big the string is in
455 pixels with a Pango layout */
456static gint
457measure_string (GtkStyle * style, PangoContext * context, const gchar * string)
458{
459 PangoLayout * layout = pango_layout_new(context);
460 pango_layout_set_text(layout, string, -1);
461 pango_layout_set_font_description(layout, style->font_desc);
462
463 gint width;
464 pango_layout_get_pixel_size(layout, &width, NULL);
465 g_object_unref(layout);
466 return width;
467}
468
469/* Try to get a good guess at what a maximum width of the entire
470 string would be. */
471static void
472guess_label_size (ApplicationEntry * app)
473{
474 /* This is during startup. */
475 if (app->entry.label == NULL) return;
476
477 GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(app->entry.label));
478 PangoContext * context = gtk_widget_get_pango_context(GTK_WIDGET(app->entry.label));
479
480 gint length = measure_string(style, context, gtk_label_get_text(app->entry.label));
481
482 if (app->guide != NULL) {
483 gint guidelen = measure_string(style, context, app->guide);
484 if (guidelen > length) {
485 length = guidelen;
486 }
487 }
488
489 gtk_widget_set_size_request(GTK_WIDGET(app->entry.label), length, -1);
490
491 return;
492}
493
494/* Here we respond to new applications by building up the
495 ApplicationEntry and signaling the indicator host that
496 we've got a new indicator. */
497static void
498application_added (DBusGProxy * proxy, const gchar * iconname, gint position, const gchar * dbusaddress, const gchar * dbusobject, const gchar * icon_theme_path, const gchar * label, const gchar * guide, IndicatorApplication * application)
499{
500 g_return_if_fail(IS_INDICATOR_APPLICATION(application));
501 g_debug("Building new application entry: %s with icon: %s", dbusaddress, iconname);
502 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
503
504 /* First search to see if we already have this entry */
505 ApplicationEntry searchapp;
506 searchapp.dbusaddress = (gchar *)dbusaddress; /* Casting off const, but it's okay, we're not changing it */
507 searchapp.dbusobject = (gchar *)dbusobject; /* Casting off const, but it's okay, we're not changing it */
508
509 GList * searchpointer = g_list_find_custom(priv->applications, &searchapp, application_added_search);
510 if (searchpointer != NULL) {
511 g_debug("\t...Already have that one.");
512 ApplicationEntry * app = (ApplicationEntry *)searchpointer->data;
513 app->old_service = FALSE;
514 return;
515 }
516
517 ApplicationEntry * app = g_new(ApplicationEntry, 1);
518
519 app->old_service = FALSE;
520 app->icon_theme_path = NULL;
521 if (icon_theme_path != NULL && icon_theme_path[0] != '\0') {
522 app->icon_theme_path = g_strdup(icon_theme_path);
523 theme_dir_ref(application, icon_theme_path);
524 }
525
526 app->dbusaddress = g_strdup(dbusaddress);
527 app->dbusobject = g_strdup(dbusobject);
528 app->guide = NULL;
529
530 /* We make a long name using the suffix, and if that
531 icon is available we want to use it. Otherwise we'll
532 just use the name we were given. */
533 app->longname = NULL;
534 if (!g_str_has_suffix(iconname, PANEL_ICON_SUFFIX)) {
535 app->longname = g_strdup_printf("%s-%s", iconname, PANEL_ICON_SUFFIX);
536 } else {
537 app->longname = g_strdup(iconname);
538 }
539 app->entry.image = indicator_image_helper(app->longname);
540
541 if (label == NULL || label[0] == '\0') {
542 app->entry.label = NULL;
543 } else {
544 app->entry.label = GTK_LABEL(gtk_label_new(label));
545 g_object_ref(G_OBJECT(app->entry.label));
546 gtk_widget_show(GTK_WIDGET(app->entry.label));
547
548 if (app->guide != NULL) {
549 g_free(app->guide);
550 app->guide = NULL;
551 }
552
553 if (guide != NULL) {
554 app->guide = g_strdup(guide);
555 }
556
557 guess_label_size(app);
558 }
559
560 app->entry.menu = GTK_MENU(dbusmenu_gtkmenu_new((gchar *)dbusaddress, (gchar *)dbusobject));
561
562 /* Keep copies of these for ourself, just in case. */
563 g_object_ref(app->entry.image);
564 g_object_ref(app->entry.menu);
565
566 gtk_widget_show(GTK_WIDGET(app->entry.image));
567
568 priv->applications = g_list_insert(priv->applications, app, position);
569
570 g_signal_emit(G_OBJECT(application), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, &(app->entry), TRUE);
571 return;
572}
573
574/* This removes the application from the list and free's all
575 of the memory associated with it. */
576static void
577application_removed (DBusGProxy * proxy, gint position, IndicatorApplication * application)
578{
579 g_return_if_fail(IS_INDICATOR_APPLICATION(application));
580 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
581 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
582
583 if (app == NULL) {
584 g_warning("Unable to find application at position: %d", position);
585 return;
586 }
587
588 priv->applications = g_list_remove(priv->applications, app);
589 g_signal_emit(G_OBJECT(application), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, &(app->entry), TRUE);
590
591 if (app->icon_theme_path != NULL) {
592 theme_dir_unref(application, app->icon_theme_path);
593 g_free(app->icon_theme_path);
594 }
595 if (app->dbusaddress != NULL) {
596 g_free(app->dbusaddress);
597 }
598 if (app->dbusobject != NULL) {
599 g_free(app->dbusobject);
600 }
601 if (app->guide != NULL) {
602 g_free(app->guide);
603 }
604 if (app->longname != NULL) {
605 g_free(app->longname);
606 }
607 if (app->entry.image != NULL) {
608 g_object_unref(G_OBJECT(app->entry.image));
609 }
610 if (app->entry.label != NULL) {
611 g_object_unref(G_OBJECT(app->entry.label));
612 }
613 if (app->entry.menu != NULL) {
614 g_object_unref(G_OBJECT(app->entry.menu));
615 }
616 g_free(app);
617
618 return;
619}
620
621/* The callback for the signal that the label for an application
622 has changed. */
623static void
624application_label_changed (DBusGProxy * proxy, gint position, const gchar * label, const gchar * guide, IndicatorApplication * application)
625{
626 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
627 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
628 gboolean signal_reload = FALSE;
629
630 if (app == NULL) {
631 g_warning("Unable to find application at position: %d", position);
632 return;
633 }
634
635 if (label == NULL || label[0] == '\0') {
636 /* No label, let's see if we need to delete the old one */
637 if (app->entry.label != NULL) {
638 g_object_unref(G_OBJECT(app->entry.label));
639 app->entry.label = NULL;
640
641 signal_reload = TRUE;
642 }
643 } else {
644 /* We've got a label, is this just an update or is
645 it a new thing. */
646 if (app->entry.label != NULL) {
647 gtk_label_set_text(app->entry.label, label);
648 } else {
649 app->entry.label = GTK_LABEL(gtk_label_new(label));
650 g_object_ref(G_OBJECT(app->entry.label));
651 gtk_widget_show(GTK_WIDGET(app->entry.label));
652
653 signal_reload = TRUE;
654 }
655 }
656
657 /* Copy the guide if we have one */
658 if (app->guide != NULL) {
659 g_free(app->guide);
660 app->guide = NULL;
661 }
662
663 if (guide != NULL && guide[0] != '\0') {
664 app->guide = g_strdup(guide);
665 }
666
667 /* Protected against not having a label */
668 guess_label_size(app);
669
670 if (signal_reload) {
671 /* Telling the listener that this has been removed, and then
672 readded to make it reparse the entry. */
673 if (app->entry.label != NULL) {
674 gtk_widget_hide(GTK_WIDGET(app->entry.label));
675 }
676
677 if (app->entry.image != NULL) {
678 gtk_widget_hide(GTK_WIDGET(app->entry.image));
679 }
680
681 if (app->entry.menu != NULL) {
682 gtk_menu_detach(app->entry.menu);
683 }
684
685 g_signal_emit(G_OBJECT(application), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, &(app->entry), TRUE);
686
687 if (app->entry.label != NULL) {
688 gtk_widget_show(GTK_WIDGET(app->entry.label));
689 }
690
691 if (app->entry.image != NULL) {
692 indicator_image_helper_update(app->entry.image, app->longname);
693 gtk_widget_show(GTK_WIDGET(app->entry.image));
694 }
695
696 g_signal_emit(G_OBJECT(application), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, &(app->entry), TRUE);
697 }
698
699 return;
700}
701
702/* The callback for the signal that the icon for an application
703 has changed. */
704static void
705application_icon_changed (DBusGProxy * proxy, gint position, const gchar * iconname, IndicatorApplication * application)
706{
707 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
708 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
709
710 if (app == NULL) {
711 g_warning("Unable to find application at position: %d", position);
712 return;
713 }
714
715 /* We make a long name using the suffix, and if that
716 icon is available we want to use it. Otherwise we'll
717 just use the name we were given. */
718 if (app->longname != NULL) {
719 g_free(app->longname);
720 app->longname = NULL;
721 }
722 if (!g_str_has_suffix(iconname, PANEL_ICON_SUFFIX)) {
723 app->longname = g_strdup_printf("%s-%s", iconname, PANEL_ICON_SUFFIX);
724 } else {
725 app->longname = g_strdup(iconname);
726 }
727 indicator_image_helper_update(app->entry.image, app->longname);
728
729 return;
730}
731
732/* The callback for the signal that the icon theme path for an application
733 has changed. */
734static void
735application_icon_theme_path_changed (DBusGProxy * proxy, gint position, const gchar * icon_theme_path, IndicatorApplication * application)
736{
737 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(application);
738 ApplicationEntry * app = (ApplicationEntry *)g_list_nth_data(priv->applications, position);
739
740 if (app == NULL) {
741 g_warning("Unable to find application at position: %d", position);
742 return;
743 }
744
745 if (g_strcmp0(icon_theme_path, app->icon_theme_path) != 0) {
746 if(app->icon_theme_path != NULL) {
747 theme_dir_unref(application, app->icon_theme_path);
748 g_free(app->icon_theme_path);
749 app->icon_theme_path = NULL;
750 }
751 if (icon_theme_path != NULL && icon_theme_path[0] != '\0') {
752 app->icon_theme_path = g_strdup(icon_theme_path);
753 theme_dir_ref(application, app->icon_theme_path);
754 }
755 indicator_image_helper_update(app->entry.image, app->longname);
756 }
757
758 return;
759}
760
761/* This repsonds to the list of applications that the service
762 has and calls application_added on each one of them. */
763static void
764get_applications (DBusGProxy *proxy, GPtrArray *OUT_applications, GError *error, gpointer userdata)
765{
766 if (error != NULL) {
767 g_warning("Unable to get application list: %s", error->message);
768 return;
769 }
770 g_ptr_array_foreach(OUT_applications, get_applications_helper, userdata);
771
772 return;
773}
774
775/* A little helper that takes apart the DBus structure and calls
776 application_added on every entry in the list. */
777static void
778get_applications_helper (gpointer data, gpointer user_data)
779{
780 GValueArray * array = (GValueArray *)data;
781
782 g_return_if_fail(array->n_values == 7);
783
784 const gchar * icon_name = g_value_get_string(g_value_array_get_nth(array, 0));
785 gint position = g_value_get_int(g_value_array_get_nth(array, 1));
786 const gchar * dbus_address = g_value_get_string(g_value_array_get_nth(array, 2));
787 const gchar * dbus_object = g_value_get_boxed(g_value_array_get_nth(array, 3));
788 const gchar * icon_theme_path = g_value_get_string(g_value_array_get_nth(array, 4));
789 const gchar * label = g_value_get_string(g_value_array_get_nth(array, 5));
790 const gchar * guide = g_value_get_string(g_value_array_get_nth(array, 6));
791
792 return application_added(NULL, icon_name, position, dbus_address, dbus_object, icon_theme_path, label, guide, user_data);
793}
794
795/* Unrefs a theme directory. This may involve removing it from
796 the search path. */
797static void
798theme_dir_unref(IndicatorApplication * ia, const gchar * dir)
799{
800 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(ia);
801
802 /* Grab the count for this dir */
803 int count = GPOINTER_TO_INT(g_hash_table_lookup(priv->theme_dirs, dir));
804
805 /* Is this a simple deprecation, if so, we can just lower the
806 number and move on. */
807 if (count > 1) {
808 count--;
809 g_hash_table_insert(priv->theme_dirs, g_strdup(dir), GINT_TO_POINTER(count));
810 return;
811 }
812
813 /* Try to remove it from the hash table, this makes sure
814 that it existed */
815 if (!g_hash_table_remove(priv->theme_dirs, dir)) {
816 g_warning("Unref'd a directory that wasn't in the theme dir hash table.");
817 return;
818 }
819
820 GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
821 gchar ** paths;
822 gint path_count;
823
824 gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
825
826 gint i;
827 gboolean found = FALSE;
828 for (i = 0; i < path_count; i++) {
829 if (found) {
830 /* If we've already found the right entry */
831 paths[i - 1] = paths[i];
832 } else {
833 /* We're still looking, is this the one? */
834 if (!g_strcmp0(paths[i], dir)) {
835 found = TRUE;
836 /* We're freeing this here as it won't be captured by the
837 g_strfreev() below as it's out of the array. */
838 g_free(paths[i]);
839 }
840 }
841 }
842
843 /* If we found one we need to reset the path to
844 accomidate the changes */
845 if (found) {
846 paths[path_count - 1] = NULL; /* Clear the last one */
847 gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, path_count - 1);
848 }
849
850 g_strfreev(paths);
851
852 return;
853}
854
855/* Refs a theme directory, and it may add it to the search
856 path */
857static void
858theme_dir_ref(IndicatorApplication * ia, const gchar * dir)
859{
860 IndicatorApplicationPrivate * priv = INDICATOR_APPLICATION_GET_PRIVATE(ia);
861
862 int count = 0;
863 if ((count = GPOINTER_TO_INT(g_hash_table_lookup(priv->theme_dirs, dir))) != 0) {
864 /* It exists so what we need to do is increase the ref
865 count of this dir. */
866 count++;
867 } else {
868 /* It doesn't exist, so we need to add it to the table
869 and to the search path. */
870 gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir);
871 g_debug("\tAppending search path: %s", dir);
872 count = 1;
873 }
874
875 g_hash_table_insert(priv->theme_dirs, g_strdup(dir), GINT_TO_POINTER(count));
876
877 return;
878}
879
8800
=== removed file 'src/notification-approver.xml'
--- src/notification-approver.xml 2010-08-18 15:31:20 +0000
+++ src/notification-approver.xml 1970-01-01 00:00:00 +0000
@@ -1,29 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<node name="/">
3 <interface name="org.ayatana.StatusNotifierApprover">
4
5<!-- Methods -->
6 <method name="ApproveItem">
7 <!-- KSNI ID -->
8 <arg type="s" name="id" direction="in" />
9 <!-- KSNI Category -->
10 <arg type="s" name="category" direction="in" />
11 <!-- Application PID -->
12 <arg type="u" name="pid" direction="in" />
13 <!-- Application DBus Address -->
14 <arg type="s" name="address" direction="in" />
15 <!-- Application DBus Path for KSNI interface -->
16 <arg type="o" name="path" direction="in" />
17 <!-- So, what do you think? -->
18 <arg type="b" name="approved" direction="out" />
19 </method>
20
21<!-- Signals -->
22 <signal name="ReviseJudgement">
23 <arg type="b" name="approved" direction="out" />
24 <arg type="s" name="address" direction="out" />
25 <arg type="o" name="path" direction="out" />
26 </signal>
27
28 </interface>
29</node>
300
=== modified file 'tests/Makefile.am'
--- tests/Makefile.am 2010-11-08 16:49:47 +0000
+++ tests/Makefile.am 2010-12-06 15:12:11 +0000
@@ -1,6 +1,5 @@
11
2check_PROGRAMS = \2check_PROGRAMS = \
3 test-approver \
4 test-libappindicator \3 test-libappindicator \
5 test-libappindicator-dbus-client \4 test-libappindicator-dbus-client \
6 test-libappindicator-dbus-server \5 test-libappindicator-dbus-server \
@@ -25,13 +24,13 @@
25 test-libappindicator.c24 test-libappindicator.c
2625
27test_libappindicator_CFLAGS = \26test_libappindicator_CFLAGS = \
28 $(INDICATOR_CFLAGS) \27 $(LIBRARY_CFLAGS) \
29 -DSRCDIR="\"$(srcdir)\"" \28 -DSRCDIR="\"$(srcdir)\"" \
30 -Wall -Werror \29 -Wall -Werror \
31 -I$(top_srcdir)/src30 -I$(top_srcdir)/src
3231
33test_libappindicator_LDADD = \32test_libappindicator_LDADD = \
34 $(INDICATOR_LIBS) \33 $(LIBRARY_LIBS) \
35 $(top_builddir)/src/libappindicator.la34 $(top_builddir)/src/libappindicator.la
3635
37#########################################36#########################################
@@ -43,12 +42,12 @@
43 test-libappindicator-dbus-client.c42 test-libappindicator-dbus-client.c
4443
45test_libappindicator_dbus_client_CFLAGS = \44test_libappindicator_dbus_client_CFLAGS = \
46 $(INDICATOR_CFLAGS) \45 $(LIBRARY_CFLAGS) \
47 -Wall -Werror \46 -Wall -Werror \
48 -I$(top_srcdir)/src47 -I$(top_srcdir)/src
4948
50test_libappindicator_dbus_client_LDADD = \49test_libappindicator_dbus_client_LDADD = \
51 $(INDICATOR_LIBS) \50 $(LIBRARY_LIBS) \
52 $(top_builddir)/src/libappindicator.la51 $(top_builddir)/src/libappindicator.la
5352
54#########################################53#########################################
@@ -60,12 +59,12 @@
60 test-libappindicator-dbus-server.c59 test-libappindicator-dbus-server.c
6160
62test_libappindicator_dbus_server_CFLAGS = \61test_libappindicator_dbus_server_CFLAGS = \
63 $(INDICATOR_CFLAGS) \62 $(LIBRARY_CFLAGS) \
64 -Wall -Werror \63 -Wall -Werror \
65 -I$(top_srcdir)/src64 -I$(top_srcdir)/src
6665
67test_libappindicator_dbus_server_LDADD = \66test_libappindicator_dbus_server_LDADD = \
68 $(INDICATOR_LIBS) \67 $(LIBRARY_LIBS) \
69 $(top_builddir)/src/libappindicator.la68 $(top_builddir)/src/libappindicator.la
7069
71#########################################70#########################################
@@ -77,12 +76,12 @@
77 test-libappindicator-status-client.c76 test-libappindicator-status-client.c
7877
79test_libappindicator_status_client_CFLAGS = \78test_libappindicator_status_client_CFLAGS = \
80 $(INDICATOR_CFLAGS) \79 $(LIBRARY_CFLAGS) \
81 -Wall -Werror \80 -Wall -Werror \
82 -I$(top_srcdir)/src81 -I$(top_srcdir)/src
8382
84test_libappindicator_status_client_LDADD = \83test_libappindicator_status_client_LDADD = \
85 $(INDICATOR_LIBS) \84 $(LIBRARY_LIBS) \
86 $(top_builddir)/src/libappindicator.la85 $(top_builddir)/src/libappindicator.la
8786
88#########################################87#########################################
@@ -94,40 +93,13 @@
94 test-libappindicator-status-server.c93 test-libappindicator-status-server.c
9594
96test_libappindicator_status_server_CFLAGS = \95test_libappindicator_status_server_CFLAGS = \
97 $(INDICATOR_CFLAGS) \96 $(LIBRARY_CFLAGS) \
98 -Wall -Werror \97 -Wall -Werror \
99 -I$(top_srcdir)/src98 -I$(top_srcdir)/src
10099
101test_libappindicator_status_server_LDADD = \100test_libappindicator_status_server_LDADD = \
102 $(INDICATOR_LIBS) \101 $(LIBRARY_LIBS) \
103 $(top_builddir)/src/libappindicator.la102 $(top_builddir)/src/libappindicator.la
104
105#########################################
106## test-approver
107#########################################
108
109test_approver_SOURCES = \
110 test-approver.c
111
112test_approver_CFLAGS = \
113 $(INDICATOR_CFLAGS) \
114 -Wall -Werror \
115 -I$(top_srcdir)/src \
116 -I$(top_builddir)/src
117
118test_approver_LDADD = \
119 $(INDICATOR_LIBS) \
120 $(top_builddir)/src/libappindicator.la
121
122test-approver-tester: test-approver Makefile.am
123 @echo "#!/bin/bash" > $@
124 @echo export INDICATOR_SERVICE_SHUTDOWN_TIMEOUT=1000 >> $@
125 @echo . $(srcdir)/run-xvfb.sh >> $@
126 @echo $(DBUS_RUNNER) --task $(builddir)/test-approver --task-name Approver --task $(top_builddir)/src/indicator-application-service --task-name Service --ignore-return >> $@
127 @chmod +x $@
128
129TESTS += test-approver-tester
130
131103
132#########################################104#########################################
133## test-libappindicator-fallback105## test-libappindicator-fallback
@@ -137,24 +109,24 @@
137 test-libappindicator-fallback-watcher.c109 test-libappindicator-fallback-watcher.c
138110
139test_libappindicator_fallback_watcher_CFLAGS = \111test_libappindicator_fallback_watcher_CFLAGS = \
140 $(INDICATOR_CFLAGS) \112 $(LIBRARY_CFLAGS) \
141 -Wall -Werror \113 -Wall -Werror \
142 -I$(top_srcdir)/src114 -I$(top_srcdir)/src
143115
144test_libappindicator_fallback_watcher_LDADD = \116test_libappindicator_fallback_watcher_LDADD = \
145 $(INDICATOR_LIBS) \117 $(LIBRARY_LIBS) \
146 $(top_builddir)/src/libappindicator.la118 $(top_builddir)/src/libappindicator.la
147119
148test_libappindicator_fallback_item_SOURCES = \120test_libappindicator_fallback_item_SOURCES = \
149 test-libappindicator-fallback-item.c121 test-libappindicator-fallback-item.c
150122
151test_libappindicator_fallback_item_CFLAGS = \123test_libappindicator_fallback_item_CFLAGS = \
152 $(INDICATOR_CFLAGS) \124 $(LIBRARY_CFLAGS) \
153 -Wall -Werror \125 -Wall -Werror \
154 -I$(top_srcdir)/src126 -I$(top_srcdir)/src
155127
156test_libappindicator_fallback_item_LDADD = \128test_libappindicator_fallback_item_LDADD = \
157 $(INDICATOR_LIBS) \129 $(LIBRARY_LIBS) \
158 $(top_builddir)/src/libappindicator.la130 $(top_builddir)/src/libappindicator.la
159131
160test-libappindicator-fallback: test-libappindicator-fallback-watcher test-libappindicator-fallback-item Makefile.am132test-libappindicator-fallback: test-libappindicator-fallback-watcher test-libappindicator-fallback-item Makefile.am
@@ -213,11 +185,11 @@
213 test-simple-app.c185 test-simple-app.c
214186
215test_simple_app_CFLAGS = \187test_simple_app_CFLAGS = \
216 $(INDICATOR_CFLAGS) \188 $(LIBRARY_CFLAGS) \
217 -Wall -Werror \189 -Wall -Werror \
218 -I$(top_srcdir)/src190 -I$(top_srcdir)/src
219191
220test_simple_app_LDADD = \192test_simple_app_LDADD = \
221 $(INDICATOR_LIBS) \193 $(LIBRARY_LIBS) \
222 $(top_builddir)/src/libappindicator.la194 $(top_builddir)/src/libappindicator.la
223195
224196
=== removed file 'tests/test-approver.c'
--- tests/test-approver.c 2010-08-19 18:56:42 +0000
+++ tests/test-approver.c 1970-01-01 00:00:00 +0000
@@ -1,179 +0,0 @@
1#include <glib.h>
2#include <glib-object.h>
3
4#include <dbus/dbus-glib-bindings.h>
5
6#include "notification-watcher-client.h"
7#include "dbus-shared.h"
8#include "app-indicator.h"
9
10#define APPROVER_PATH "/my/approver"
11
12#define INDICATOR_ID "test-indicator-id"
13#define INDICATOR_ICON "test-indicator-icon-name"
14#define INDICATOR_CATEGORY APP_INDICATOR_CATEGORY_APPLICATION_STATUS
15
16#define TEST_APPROVER_TYPE (test_approver_get_type ())
17#define TEST_APPROVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_APPROVER_TYPE, TestApprover))
18#define TEST_APPROVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_APPROVER_TYPE, TestApproverClass))
19#define IS_TEST_APPROVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_APPROVER_TYPE))
20#define IS_TEST_APPROVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_APPROVER_TYPE))
21#define TEST_APPROVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_APPROVER_TYPE, TestApproverClass))
22
23typedef struct _TestApprover TestApprover;
24typedef struct _TestApproverClass TestApproverClass;
25
26struct _TestApproverClass {
27 GObjectClass parent_class;
28};
29
30struct _TestApprover {
31 GObject parent;
32};
33
34GType test_approver_get_type (void);
35
36static void test_approver_class_init (TestApproverClass *klass);
37static void test_approver_init (TestApprover *self);
38static gboolean _notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error);
39
40#include "../src/notification-approver-server.h"
41
42GMainLoop * main_loop = NULL;
43DBusGConnection * session_bus = NULL;
44DBusGProxy * bus_proxy = NULL;
45AppIndicator * app_indicator = NULL;
46gboolean passed = FALSE;
47
48G_DEFINE_TYPE (TestApprover, test_approver, G_TYPE_OBJECT);
49
50static void
51test_approver_class_init (TestApproverClass *klass)
52{
53 dbus_g_object_type_install_info(TEST_APPROVER_TYPE,
54 &dbus_glib__notification_approver_server_object_info);
55
56 return;
57}
58
59static void
60test_approver_init (TestApprover *self)
61{
62 dbus_g_connection_register_g_object(session_bus,
63 APPROVER_PATH,
64 G_OBJECT(self));
65
66 return;
67}
68
69static gboolean
70_notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error)
71{
72 *approved = TRUE;
73 g_debug("Asked to approve indicator");
74
75 if (g_strcmp0(id, INDICATOR_ID) == 0) {
76 passed = TRUE;
77 }
78
79 g_main_loop_quit(main_loop);
80
81 return TRUE;
82}
83
84static void
85register_cb (DBusGProxy * proxy, GError * error, gpointer user_data)
86{
87 if (error != NULL) {
88 g_warning("Unable to register approver: %s", error->message);
89 g_error_free(error);
90 g_main_loop_quit(main_loop);
91 return;
92 }
93
94 g_debug("Building App Indicator");
95 app_indicator = app_indicator_new(INDICATOR_ID, INDICATOR_ICON, INDICATOR_CATEGORY);
96
97 GtkWidget * menu = gtk_menu_new();
98 GtkWidget * mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
99 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
100
101 app_indicator_set_menu(app_indicator, GTK_MENU(menu));
102
103 return;
104}
105
106gint owner_count = 0;
107gboolean
108check_for_service (gpointer user_data)
109{
110 g_debug("Checking for Watcher");
111
112 if (owner_count > 100) {
113 g_warning("Couldn't find watcher after 100 tries.");
114 g_main_loop_quit(main_loop);
115 return FALSE;
116 }
117
118 owner_count++;
119
120 gboolean has_owner = FALSE;
121 org_freedesktop_DBus_name_has_owner(bus_proxy, NOTIFICATION_WATCHER_DBUS_ADDR, &has_owner, NULL);
122
123 if (has_owner) {
124 const char * cats = NULL;
125 DBusGProxy * proxy = dbus_g_proxy_new_for_name(session_bus,
126 NOTIFICATION_WATCHER_DBUS_ADDR,
127 NOTIFICATION_WATCHER_DBUS_OBJ,
128 NOTIFICATION_WATCHER_DBUS_IFACE);
129
130 g_debug("Registering Approver");
131 org_kde_StatusNotifierWatcher_x_ayatana_register_notification_approver_async (proxy, APPROVER_PATH, &cats, register_cb, NULL);
132
133 return FALSE;
134 }
135
136 return TRUE;
137}
138
139gboolean
140fail_timeout (gpointer user_data)
141{
142 g_debug("Failure timeout initiated.");
143 g_main_loop_quit(main_loop);
144 return FALSE;
145}
146
147int
148main (int argc, char ** argv)
149{
150 GError * error = NULL;
151
152 gtk_init(&argc, &argv);
153 g_debug("Initing");
154
155 session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
156 if (error != NULL) {
157 g_warning("Unable to get session bus: %s", error->message);
158 g_error_free(error);
159 return -1;
160 }
161
162 TestApprover * approver = g_object_new(TEST_APPROVER_TYPE, NULL);
163
164 bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
165
166 g_timeout_add(100, check_for_service, NULL);
167 g_timeout_add_seconds(2, fail_timeout, NULL);
168
169 main_loop = g_main_loop_new(NULL, FALSE);
170 g_main_loop_run(main_loop);
171
172 g_object_unref(approver);
173
174 if (!passed) {
175 return -1;
176 }
177
178 return 0;
179}

Subscribers

People subscribed via source and target branches