Merge lp:indicator-messages/phablet into lp:~indicator-applet-developers/indicator-messages/trunk.13.10

Proposed by Ted Gould
Status: Merged
Merged at revision: 352
Proposed branch: lp:indicator-messages/phablet
Merge into: lp:~indicator-applet-developers/indicator-messages/trunk.13.10
Diff against target: 6026 lines (+3890/-1245) (has conflicts)
35 files modified
COPYING.GPLv3 (+674/-0)
Makefile.am (+1/-0)
autogen.sh (+11/-5)
common/Makefile.am (+32/-0)
common/com.canonical.indicator.messages.application.xml (+39/-0)
configure.ac (+18/-0)
debian/changelog (+90/-0)
debian/control (+13/-5)
debian/libmessaging-menu-dev.install (+1/-0)
debian/libmessaging-menu0.symbols (+15/-0)
debian/source/format (+1/-0)
doc/reference/Makefile.am (+1/-2)
doc/reference/messaging-menu-docs.xml.in (+2/-1)
libmessaging-menu/Makefile.am (+33/-22)
libmessaging-menu/gtupleaction.c (+0/-354)
libmessaging-menu/gtupleaction.h (+0/-40)
libmessaging-menu/messaging-menu-app.c (+512/-186)
libmessaging-menu/messaging-menu-app.h (+17/-2)
libmessaging-menu/messaging-menu-message.c (+547/-0)
libmessaging-menu/messaging-menu-message.h (+70/-0)
libmessaging-menu/messaging-menu.h (+25/-0)
src/Makefile.am (+11/-25)
src/app-section.c (+278/-170)
src/dbus-data.h (+16/-1)
src/gactionmuxer.c (+8/-0)
src/gactionmuxer.h (+3/-0)
src/ido-detail-label.c (+15/-0)
src/im-application-list.c (+880/-0)
src/im-application-list.h (+52/-0)
src/im-phone-menu.c (+331/-0)
src/im-phone-menu.h (+70/-0)
src/messages-service.c (+68/-430)
test/Makefile.am (+3/-2)
test/indicator-messages-service-activate.c (+7/-0)
test/test-gactionmuxer.cpp (+46/-0)
Text conflict in debian/changelog
Text conflict in debian/control
Text conflict in libmessaging-menu/messaging-menu-app.c
Text conflict in src/app-section.c
Text conflict in src/ido-detail-label.c
Text conflict in src/messages-service.c
Text conflict in test/indicator-messages-service-activate.c
Text conflict in test/test-gactionmuxer.cpp
To merge this branch: bzr merge lp:indicator-messages/phablet
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+167165@code.launchpad.net

Commit message

Merge in phablet branch.

To post a comment you must log in.
lp:indicator-messages/phablet updated
364. By Ken VanDine

Fixed deprecations.

Approved by Charles Kerr, PS Jenkins bot.

365. By Ken VanDine

Generate a vapi, added valac build depends and reordered the build depends to be alphabetical.

Approved by PS Jenkins bot, Charles Kerr.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'COPYING.GPLv3'
--- COPYING.GPLv3 1970-01-01 00:00:00 +0000
+++ COPYING.GPLv3 2013-07-12 19:50:34 +0000
@@ -0,0 +1,674 @@
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>.
0675
=== modified file 'Makefile.am'
--- Makefile.am 2012-08-29 11:27:54 +0000
+++ Makefile.am 2013-07-12 19:50:34 +0000
@@ -1,5 +1,6 @@
11
2SUBDIRS = \2SUBDIRS = \
3 common \
3 src \4 src \
4 libmessaging-menu \5 libmessaging-menu \
5 data \6 data \
67
=== modified file 'autogen.sh'
--- autogen.sh 2012-08-29 11:27:54 +0000
+++ autogen.sh 2013-07-12 19:50:34 +0000
@@ -1,5 +1,11 @@
1#!/bin/sh -e1#!/bin/sh
22
3gtkdocize3PKG_NAME="indicator-messages"
4autoreconf -i -f4
5intltoolize5which gnome-autogen.sh || {
6 echo "You need gnome-common from GNOME SVN"
7 exit 1
8}
9
10USE_GNOME2_MACROS=1 \
11. gnome-autogen.sh
612
=== added directory 'common'
=== added file 'common/Makefile.am'
--- common/Makefile.am 1970-01-01 00:00:00 +0000
+++ common/Makefile.am 2013-07-12 19:50:34 +0000
@@ -0,0 +1,32 @@
1
2noinst_LTLIBRARIES = libmessaging-common.la
3
4indicator-messages-service.c: com.canonical.indicator.messages.service.xml
5 $(AM_V_GEN) gdbus-codegen \
6 --interface-prefix com.canonical.indicator.messages. \
7 --generate-c-code indicator-messages-service \
8 --c-namespace IndicatorMessages \
9 $^
10indicator-messages-service.h: indicator-messages-service.c
11
12indicator-messages-application.c: com.canonical.indicator.messages.application.xml
13 $(AM_V_GEN) gdbus-codegen \
14 --interface-prefix com.canonical.indicator.messages. \
15 --generate-c-code indicator-messages-application \
16 --c-namespace IndicatorMessages \
17 $^
18indicator-messages-application.h: indicator-messages-application.c
19
20BUILT_SOURCES = \
21 indicator-messages-service.c \
22 indicator-messages-service.h \
23 indicator-messages-application.c \
24 indicator-messages-application.h
25
26libmessaging_common_la_SOURCES = \
27 $(BUILT_SOURCES)
28
29libmessaging_common_la_CFLAGS = $(GIO_CFLAGS)
30libmessaging_common_la_LIBADD = $(GIO_LIBS)
31
32CLEANFILES = $(BUILT_SOURCES)
033
=== added file 'common/com.canonical.indicator.messages.application.xml'
--- common/com.canonical.indicator.messages.application.xml 1970-01-01 00:00:00 +0000
+++ common/com.canonical.indicator.messages.application.xml 2013-07-12 19:50:34 +0000
@@ -0,0 +1,39 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<node name="/">
3 <interface name="com.canonical.indicator.messages.application">
4 <method name="ListSources">
5 <arg type="a(sssuxsb)" name="sources" direction="out" />
6 </method>
7 <method name="ListMessages">
8 <arg type="a(sssssxaa{sv}b)" name="message" direction="out" />
9 </method>
10 <method name="ActivateSource">
11 <arg type="s" name="source_id" direction="in" />
12 </method>
13 <method name="ActivateMessage">
14 <arg type="s" name="message_id" direction="in" />
15 <arg type="s" name="action_id" direction="in" />
16 <arg type="av" name="parameter" direction="in" />
17 </method>
18 <method name="Dismiss">
19 <arg type="as" name="sources" direction="in" />
20 <arg type="as" name="messages" direction="in" />
21 </method>
22 <signal name="SourceAdded">
23 <arg type="u" name="position" direction="in" />
24 <arg type="(sssuxsb)" name="source" direction="in" />
25 </signal>
26 <signal name="SourceChanged">
27 <arg type="(sssuxsb)" name="source" direction="in" />
28 </signal>
29 <signal name="SourceRemoved">
30 <arg type="s" name="source_id" direction="in" />
31 </signal>
32 <signal name="MessageAdded">
33 <arg type="(sssssxaa{sv}b)" name="message" direction="in" />
34 </signal>
35 <signal name="MessageRemoved">
36 <arg type="s" name="message_id" direction="in" />
37 </signal>
38 </interface>
39</node>
040
=== renamed file 'src/messages-service.xml' => 'common/com.canonical.indicator.messages.service.xml'
=== modified file 'configure.ac'
--- configure.ac 2013-02-26 00:34:56 +0000
+++ configure.ac 2013-07-12 19:50:34 +0000
@@ -128,6 +128,22 @@
128fi128fi
129AC_SUBST(DBUSSERVICEDIR)129AC_SUBST(DBUSSERVICEDIR)
130130
131###########################
132# Vala API Generation
133###########################
134
135AC_ARG_ENABLE([vala],
136 AC_HELP_STRING([--disable-vala], [Disable vala]),
137 [enable_vala=$enableval], [enable_vala=yes])
138
139AS_IF([test "x$enable_vala" != "xno"],[
140 AM_COND_IF([HAVE_INTROSPECTION],,[
141 AC_MSG_ERROR([Vala bindings require introspection support, please --enable-introspection])
142 ])
143AC_PATH_PROG([VALA_API_GEN], [vapigen])
144])
145AM_CONDITIONAL([HAVE_VALA], [test -n "$VALA_API_GEN"])
146
131##############################147##############################
132# Custom Junk148# Custom Junk
133##############################149##############################
@@ -162,6 +178,7 @@
162AC_OUTPUT([178AC_OUTPUT([
163Makefile179Makefile
164src/Makefile180src/Makefile
181common/Makefile
165data/Makefile182data/Makefile
166data/icons/Makefile183data/icons/Makefile
167data/icons/16x16/Makefile184data/icons/16x16/Makefile
@@ -202,5 +219,6 @@
202 tests: $enable_tests219 tests: $enable_tests
203 gcov: $use_gcov220 gcov: $use_gcov
204 introspecion: $enable_introspection221 introspecion: $enable_introspection
222 Vala bindings: $enable_vala
205 documentation: $enable_gtk_doc223 documentation: $enable_gtk_doc
206])224])
207225
=== modified file 'debian/changelog'
--- debian/changelog 2013-07-02 02:02:36 +0000
+++ debian/changelog 2013-07-12 19:50:34 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1indicator-messages (12.10.6+13.10.20130702-0ubuntu1) saucy; urgency=low2indicator-messages (12.10.6+13.10.20130702-0ubuntu1) saucy; urgency=low
23
3 [ Mathias Dietrich ]4 [ Mathias Dietrich ]
@@ -104,6 +105,88 @@
104indicator-messages (12.10.6daily12.11.21.1-0ubuntu1) raring; urgency=low105indicator-messages (12.10.6daily12.11.21.1-0ubuntu1) raring; urgency=low
105106
106 [ Mathieu Trudel-Lapierre ]107 [ Mathieu Trudel-Lapierre ]
108=======
109indicator-messages (13.10.0phablet1) raring; urgency=low
110
111 * Version bump to not pull from archives
112
113 -- Sergio Schvezov <sergio.schvezov@canonical.com> Fri, 26 Apr 2013 13:53:53 -0300
114
115indicator-messages (12.10.6phablet1) quantal; urgency=low
116
117 * Adding guards for g_type_init
118
119 -- Sergio Schvezov <sergio.schvezov@canonical.com> Fri, 22 Mar 2013 17:23:45 -0300
120
121indicator-messages (12.10.6-0ubuntu1phablet9) quantal; urgency=low
122
123 * add "remove-all" signal to imapplicationlist (temporarily)
124
125 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 20 Dec 2012 18:49:50 +0100
126
127indicator-messages (12.10.6-0ubuntu1phablet8) quantal; urgency=low
128
129 * Make messaging_menu_app_remove_message() work for messages with a ref count of 1
130 * Make handling of multiple processes with the same desktop id more robust
131 * ImPhoneMenu: sort messages by time (fixes LP #1090266)
132 * Don't show message sources
133
134 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 17 Dec 2012 14:42:03 +0100
135
136indicator-messages (12.10.6-0ubuntu1phablet7) quantal; urgency=low
137
138 * Remove variant wrapper from 'parameter' argument of the "activate" signal
139
140 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Tue, 11 Dec 2012 14:28:15 +0100
141
142indicator-messages (12.10.6-0ubuntu1phablet6) quantal; urgency=low
143
144 * Don't show sources
145 * Always use the "messageitem" widget type for messages
146
147 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 10 Dec 2012 14:38:16 +0100
148
149indicator-messages (12.10.6-0ubuntu1phablet5) quantal; urgency=low
150
151 * Don't shorten the app id to seven characters (fixes LP #1086729)
152 * Add messaging_menu_app_get_message
153
154 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 06 Dec 2012 15:06:34 +0000
155
156indicator-messages (12.10.6-0ubuntu1phablet4) quantal; urgency=low
157
158 [Lars Uebernickel]
159 * Add the concept of actions to messages
160 * Stop using IndicatorService
161 * Reverse order of messages
162 * Expose symbolic application icon
163 * Change icon when there are any messages in the menu
164
165 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Tue, 04 Dec 2012 21:10:26 +0000
166
167indicator-messages (12.10.6-0ubuntu1phablet3) quantal; urgency=low
168
169 [Lars Uebernickel]
170 * expose root menu item of which the indicator menu is a submenu
171 * fix crash in im-application-list on arm
172
173 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 29 Nov 2012 21:44:19 +0100
174
175indicator-messages (12.10.6-0ubuntu1phablet2) quantal; urgency=low
176
177 [Lars Uebernickel]
178 * refactor messages-service.c
179 * notify applications about message and source activations
180 * add "Clear All" menu item
181 * allow dismissing of messages
182 * include application icons on message items
183
184 -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 26 Nov 2012 22:19:51 +0100
185
186indicator-messages (12.10.6-0ubuntu1phablet1) quantal; urgency=low
187
188 [ Mathieu Trudel-Lapierre ]
189>>>>>>> MERGE-SOURCE
107 * debian/rules:190 * debian/rules:
108 - Use autogen.sh for dh_autoreconf.191 - Use autogen.sh for dh_autoreconf.
109 - Drop the override for dh_makeshlibs.192 - Drop the override for dh_makeshlibs.
@@ -116,10 +199,17 @@
116 - Clear the detail (count or time) of a source when another type of detail199 - Clear the detail (count or time) of a source when another type of detail
117 is set. (LP: #1071640)200 is set. (LP: #1071640)
118201
202<<<<<<< TREE
119 [ Automatic PS uploader ]203 [ Automatic PS uploader ]
120 * Automatic snapshot from revision 331204 * Automatic snapshot from revision 331
121205
122 -- Automatic PS uploader <ps-jenkins@lists.canonical.com> Wed, 21 Nov 2012 10:41:37 +0000206 -- Automatic PS uploader <ps-jenkins@lists.canonical.com> Wed, 21 Nov 2012 10:41:37 +0000
207=======
208 [ Ricardo Mendoza ]
209 * Releasing upstream for phablet
210
211 -- Ricardo Mendoza <ricardo.mendoza@canonical.com> Tue, 20 Nov 2012 10:08:59 -0430
212>>>>>>> MERGE-SOURCE
123213
124indicator-messages (12.10.5-0ubuntu2) raring; urgency=low214indicator-messages (12.10.5-0ubuntu2) raring; urgency=low
125215
126216
=== modified file 'debian/control'
--- debian/control 2013-06-07 22:15:28 +0000
+++ debian/control 2013-07-12 19:50:34 +0000
@@ -7,19 +7,27 @@
7Build-Depends: debhelper (>= 9),7Build-Depends: debhelper (>= 9),
8 dh-autoreconf,8 dh-autoreconf,
9 dh-translations,9 dh-translations,
10<<<<<<< TREE
10 libglib2.0-dev (>= 2.35.4),11 libglib2.0-dev (>= 2.35.4),
11 libgtk-3-dev (>= 3.5.12),12 libgtk-3-dev (>= 3.5.12),
13=======
14 gobject-introspection (>= 0.9.12-4~),
15 gtk-doc-tools,
16 intltool,
17>>>>>>> MERGE-SOURCE
12 libdbus-glib-1-dev,18 libdbus-glib-1-dev,
13 intltool,
14 libindicator3-dev,
15 libdbusmenu-glib-dev (>= 0.5.90),19 libdbusmenu-glib-dev (>= 0.5.90),
16 libdbusmenu-gtk3-dev (>= 0.5.90),20 libdbusmenu-gtk3-dev (>= 0.5.90),
17 libtelepathy-glib-dev (>= 0.9.0),
18 gobject-introspection (>= 0.9.12-4~),
19 libgirepository1.0-dev (>= 0.9.12),21 libgirepository1.0-dev (>= 0.9.12),
20 gtk-doc-tools,
21 libgtest-dev,22 libgtest-dev,
23<<<<<<< TREE
22 python3-dbusmock,24 python3-dbusmock,
25=======
26 libgtk-3-dev (>= 3.5.18),
27 libindicator3-dev,
28 libtelepathy-glib-dev (>= 0.9.0),
29 valac,
30>>>>>>> MERGE-SOURCE
23Standards-Version: 3.9.331Standards-Version: 3.9.3
24Homepage: https://launchpad.net/indicator-messages32Homepage: https://launchpad.net/indicator-messages
25# If you aren't a member of ~indicator-applet-developers but need to upload33# If you aren't a member of ~indicator-applet-developers but need to upload
2634
=== modified file 'debian/libmessaging-menu-dev.install'
--- debian/libmessaging-menu-dev.install 2012-09-01 10:35:36 +0000
+++ debian/libmessaging-menu-dev.install 2013-07-12 19:50:34 +0000
@@ -2,4 +2,5 @@
2usr/lib/pkgconfig2usr/lib/pkgconfig
3usr/include /usr/3usr/include /usr/
4usr/share/gir-1.0/4usr/share/gir-1.0/
5usr/share/vala/
5usr/share/gtk-doc6usr/share/gtk-doc
67
=== modified file 'debian/libmessaging-menu0.symbols'
--- debian/libmessaging-menu0.symbols 2012-09-01 10:35:36 +0000
+++ debian/libmessaging-menu0.symbols 2013-07-12 19:50:34 +0000
@@ -1,9 +1,11 @@
1libmessaging-menu.so.0 libmessaging-menu0 #MINVER#1libmessaging-menu.so.0 libmessaging-menu0 #MINVER#
2 messaging_menu_app_append_message@Base 12.10.6-0ubuntu1phablet1
2 messaging_menu_app_append_source@Base 12.10.03 messaging_menu_app_append_source@Base 12.10.0
3 messaging_menu_app_append_source_with_count@Base 12.10.04 messaging_menu_app_append_source_with_count@Base 12.10.0
4 messaging_menu_app_append_source_with_string@Base 12.10.05 messaging_menu_app_append_source_with_string@Base 12.10.0
5 messaging_menu_app_append_source_with_time@Base 12.10.06 messaging_menu_app_append_source_with_time@Base 12.10.0
6 messaging_menu_app_draw_attention@Base 12.10.07 messaging_menu_app_draw_attention@Base 12.10.0
8 messaging_menu_app_get_message@Base 0replaceme
7 messaging_menu_app_get_type@Base 12.10.09 messaging_menu_app_get_type@Base 12.10.0
8 messaging_menu_app_has_source@Base 12.10.010 messaging_menu_app_has_source@Base 12.10.0
9 messaging_menu_app_insert_source@Base 12.10.011 messaging_menu_app_insert_source@Base 12.10.0
@@ -13,6 +15,8 @@
13 messaging_menu_app_new@Base 12.10.015 messaging_menu_app_new@Base 12.10.0
14 messaging_menu_app_register@Base 12.10.016 messaging_menu_app_register@Base 12.10.0
15 messaging_menu_app_remove_attention@Base 12.10.017 messaging_menu_app_remove_attention@Base 12.10.0
18 messaging_menu_app_remove_message@Base 12.10.6-0ubuntu1phablet1
19 messaging_menu_app_remove_message_by_id@Base 12.10.6-0ubuntu1phablet1
16 messaging_menu_app_remove_source@Base 12.10.020 messaging_menu_app_remove_source@Base 12.10.0
17 messaging_menu_app_set_source_count@Base 12.10.021 messaging_menu_app_set_source_count@Base 12.10.0
18 messaging_menu_app_set_source_icon@Base 12.10.222 messaging_menu_app_set_source_icon@Base 12.10.2
@@ -21,3 +25,14 @@
21 messaging_menu_app_set_source_time@Base 12.10.025 messaging_menu_app_set_source_time@Base 12.10.0
22 messaging_menu_app_set_status@Base 12.10.026 messaging_menu_app_set_status@Base 12.10.0
23 messaging_menu_app_unregister@Base 12.10.027 messaging_menu_app_unregister@Base 12.10.0
28 messaging_menu_message_add_action@Base 12.10.6-0ubuntu1phablet3
29 messaging_menu_message_get_body@Base 12.10.6-0ubuntu1phablet1
30 messaging_menu_message_get_draws_attention@Base 12.10.6-0ubuntu1phablet1
31 messaging_menu_message_get_icon@Base 12.10.6-0ubuntu1phablet1
32 messaging_menu_message_get_id@Base 12.10.6-0ubuntu1phablet1
33 messaging_menu_message_get_subtitle@Base 12.10.6-0ubuntu1phablet1
34 messaging_menu_message_get_time@Base 12.10.6-0ubuntu1phablet1
35 messaging_menu_message_get_title@Base 12.10.6-0ubuntu1phablet1
36 messaging_menu_message_get_type@Base 12.10.6-0ubuntu1phablet1
37 messaging_menu_message_new@Base 12.10.6-0ubuntu1phablet1
38 messaging_menu_message_set_draws_attention@Base 12.10.6-0ubuntu1phablet1
2439
=== added directory 'debian/source'
=== added file 'debian/source/format'
--- debian/source/format 1970-01-01 00:00:00 +0000
+++ debian/source/format 2013-07-12 19:50:34 +0000
@@ -0,0 +1,1 @@
11.0
02
=== modified file 'doc/reference/Makefile.am'
--- doc/reference/Makefile.am 2013-01-22 20:23:57 +0000
+++ doc/reference/Makefile.am 2013-07-12 19:50:34 +0000
@@ -11,8 +11,7 @@
11CFILE_GLOB = $(top_srcdir)/libmessaging-menu/*.c11CFILE_GLOB = $(top_srcdir)/libmessaging-menu/*.c
1212
13IGNORE_HFILES= \13IGNORE_HFILES= \
14 indicator-messages-service.h \14 indicator-messages-service.h
15 gtupleaction.h
1615
17INCLUDES=-I$(top_srcdir)/libmessaging-menu $(GIO_CFLAGS)16INCLUDES=-I$(top_srcdir)/libmessaging-menu $(GIO_CFLAGS)
18GTKDOC_LIBS=$(top_builddir)/libmessaging-menu/libmessaging-menu.la17GTKDOC_LIBS=$(top_builddir)/libmessaging-menu/libmessaging-menu.la
1918
=== modified file 'doc/reference/messaging-menu-docs.xml.in'
--- doc/reference/messaging-menu-docs.xml.in 2012-08-29 11:27:54 +0000
+++ doc/reference/messaging-menu-docs.xml.in 2013-07-12 19:50:34 +0000
@@ -18,7 +18,8 @@
1818
19 <chapter>19 <chapter>
20 <title>API Reference</title>20 <title>API Reference</title>
21 <xi:include href="xml/messaging-menu.xml"/>21 <xi:include href="xml/messaging-menu-app.xml" />
22 <xi:include href="xml/messaging-menu-message.xml" />
22 </chapter>23 </chapter>
2324
24 <chapter id="object-tree">25 <chapter id="object-tree">
2526
=== modified file 'libmessaging-menu/Makefile.am'
--- libmessaging-menu/Makefile.am 2012-09-01 08:27:34 +0000
+++ libmessaging-menu/Makefile.am 2013-07-12 19:50:34 +0000
@@ -4,36 +4,25 @@
4libmessaging_menu_ladir = $(includedir)/messaging-menu4libmessaging_menu_ladir = $(includedir)/messaging-menu
55
6libmessaging_menu_la_SOURCES = \6libmessaging_menu_la_SOURCES = \
7 messaging-menu.c \7 messaging-menu-app.c \
8 gtupleaction.c \8 messaging-menu-message.c
9 gtupleaction.h \
10 $(BUILT_SOURCES)
119
12libmessaging_menu_la_HEADERS = \10libmessaging_menu_la_HEADERS = \
13 messaging-menu.h11 messaging-menu-app.h \
12 messaging-menu.h \
13 messaging-menu-message.h
1414
15libmessaging_menu_la_LIBADD = $(GIO_LIBS)15libmessaging_menu_la_LIBADD = \
16 $(GIO_LIBS) \
17 $(top_builddir)/common/libmessaging-common.la
1618
17libmessaging_menu_la_CFLAGS = \19libmessaging_menu_la_CFLAGS = \
20 -I$(top_builddir)/common \
18 $(GIO_CFLAGS) \21 $(GIO_CFLAGS) \
19 -Wall22 -Wall
2023
21libmessaging_menu_la_LDFLAGS = -export-symbols-regex "^messaging_menu_.*"24libmessaging_menu_la_LDFLAGS = -export-symbols-regex "^messaging_menu_.*"
2225
23BUILT_SOURCES = \
24 indicator-messages-service.c \
25 indicator-messages-service.h
26
27CLEANFILES = $(BUILT_SOURCES)
28
29indicator-messages-service.c: $(top_srcdir)/src/messages-service.xml
30 $(AM_V_GEN) gdbus-codegen \
31 --interface-prefix com.canonical.indicator.messages. \
32 --generate-c-code indicator-messages-service \
33 --c-namespace IndicatorMessages \
34 $^
35indicator-messages-service.h: indicator-messages-service.c
36
37pkgconfigdir = $(libdir)/pkgconfig26pkgconfigdir = $(libdir)/pkgconfig
38pkgconfig_DATA = messaging-menu.pc27pkgconfig_DATA = messaging-menu.pc
3928
@@ -52,7 +41,11 @@
52MessagingMenu_1_0_gir_CFLAGS = $(INCLUDES) $(GIO_CFLAGS)41MessagingMenu_1_0_gir_CFLAGS = $(INCLUDES) $(GIO_CFLAGS)
53MessagingMenu_1_0_gir_SCANNERFLAGS = --c-include="messaging-menu.h"42MessagingMenu_1_0_gir_SCANNERFLAGS = --c-include="messaging-menu.h"
54MessagingMenu_1_0_gir_LIBS = libmessaging-menu.la43MessagingMenu_1_0_gir_LIBS = libmessaging-menu.la
55MessagingMenu_1_0_gir_FILES = messaging-menu.c messaging-menu.h44MessagingMenu_1_0_gir_FILES = \
45 messaging-menu-app.c \
46 messaging-menu-app.h \
47 messaging-menu-message.c \
48 messaging-menu-message.h
56MessagingMenu_1_0_gir_EXPORT_PACKAGES = messaging-menu49MessagingMenu_1_0_gir_EXPORT_PACKAGES = messaging-menu
57INTROSPECTION_GIRS += MessagingMenu-1.0.gir50INTROSPECTION_GIRS += MessagingMenu-1.0.gir
5851
@@ -62,5 +55,23 @@
62typelibdir = $(libdir)/girepository-1.055typelibdir = $(libdir)/girepository-1.0
63typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)56typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
6457
65CLEANFILES +=$(gir_DATA) $(typelib_DATA)58CLEANFILES = $(gir_DATA) $(typelib_DATA)
59
60
61#########################
62# VAPI Files
63#########################
64
65if HAVE_VALA
66
67vapidir = $(datadir)/vala/vapi
68vapi_DATA = MessagingMenu-1.0.vapi
69
70MessagingMenu-1.0.vapi: MessagingMenu-1.0.gir
71 $(VALA_API_GEN) --pkg gio-2.0 --library=MessagingMenu-1.0 $<
72
73CLEANFILES += $(vapi_DATA)
74
75endif
76
66endif77endif
6778
=== removed file 'libmessaging-menu/gtupleaction.c'
--- libmessaging-menu/gtupleaction.c 2012-08-20 21:09:54 +0000
+++ libmessaging-menu/gtupleaction.c 1970-01-01 00:00:00 +0000
@@ -1,354 +0,0 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#include "gtupleaction.h"
21
22typedef GObjectClass GTupleActionClass;
23
24struct _GTupleAction
25{
26 GObject parent;
27
28 gchar *name;
29 GVariantType *type;
30 gboolean enabled;
31
32 gsize n_children;
33 GVariant **children;
34};
35
36static void action_interface_init (GActionInterface *iface);
37
38G_DEFINE_TYPE_WITH_CODE (GTupleAction, g_tuple_action, G_TYPE_OBJECT,
39 G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, action_interface_init));
40
41enum
42{
43 PROP_0,
44 PROP_NAME,
45 PROP_PARAMETER_TYPE,
46 PROP_ENABLED,
47 PROP_STATE_TYPE,
48 PROP_STATE,
49 N_PROPERTIES
50};
51
52enum
53{
54 SIGNAL_ACTIVATE,
55 N_SIGNALS
56};
57
58static GParamSpec *properties[N_PROPERTIES];
59static guint signal_ids[N_SIGNALS];
60
61static const gchar *
62g_tuple_action_get_name (GAction *action)
63{
64 GTupleAction *tuple = G_TUPLE_ACTION (action);
65
66 return tuple->name;
67}
68
69static const GVariantType *
70g_tuple_action_get_parameter_type (GAction *action)
71{
72 return NULL;
73}
74
75static const GVariantType *
76g_tuple_action_get_state_type (GAction *action)
77{
78 GTupleAction *tuple = G_TUPLE_ACTION (action);
79
80 return tuple->type;
81}
82
83static GVariant *
84g_tuple_action_get_state_hint (GAction *action)
85{
86 return NULL;
87}
88
89static gboolean
90g_tuple_action_get_enabled (GAction *action)
91{
92 GTupleAction *tuple = G_TUPLE_ACTION (action);
93
94 return tuple->enabled;
95}
96
97static GVariant *
98g_tuple_action_get_state (GAction *action)
99{
100 GTupleAction *tuple = G_TUPLE_ACTION (action);
101 GVariant *result;
102
103 result = g_variant_new_tuple (tuple->children, tuple->n_children);
104 return g_variant_ref_sink (result);
105}
106
107static void
108g_tuple_action_set_state (GTupleAction *tuple,
109 GVariant *state)
110{
111 int i;
112
113 g_return_if_fail (g_variant_type_is_tuple (g_variant_get_type (state)));
114
115 if (tuple->type == NULL)
116 {
117 tuple->type = g_variant_type_copy (g_variant_get_type (state));
118 tuple->n_children = g_variant_n_children (state);
119 tuple->children = g_new0 (GVariant *, tuple->n_children);
120 }
121
122 for (i = 0; i < tuple->n_children; i++)
123 {
124 if (tuple->children[i])
125 g_variant_unref (tuple->children[i]);
126 tuple->children[i] = g_variant_get_child_value (state, i);
127 }
128
129 g_object_notify_by_pspec (G_OBJECT (tuple), properties[PROP_STATE]);
130}
131
132static void
133g_tuple_action_change_state (GAction *action,
134 GVariant *value)
135{
136 GTupleAction *tuple = G_TUPLE_ACTION (action);
137
138 g_return_if_fail (value != NULL);
139 g_return_if_fail (g_variant_is_of_type (value, tuple->type));
140
141 g_variant_ref_sink (value);
142
143 /* TODO add a change-state signal similar to GSimpleAction */
144 g_tuple_action_set_state (tuple, value);
145
146 g_variant_unref (value);
147}
148
149static void
150g_tuple_action_activate (GAction *action,
151 GVariant *parameter)
152{
153 GTupleAction *tuple = G_TUPLE_ACTION (action);
154
155 g_return_if_fail (parameter == NULL);
156
157 if (tuple->enabled)
158 g_signal_emit (tuple, signal_ids[SIGNAL_ACTIVATE], 0, NULL);
159}
160
161static void
162g_tuple_action_get_property (GObject *object,
163 guint prop_id,
164 GValue *value,
165 GParamSpec *pspec)
166{
167 GAction *action = G_ACTION (object);
168
169 switch (prop_id)
170 {
171 case PROP_NAME:
172 g_value_set_string (value, g_tuple_action_get_name (action));
173 break;
174
175 case PROP_PARAMETER_TYPE:
176 g_value_set_boxed (value, g_tuple_action_get_parameter_type (action));
177 break;
178
179 case PROP_ENABLED:
180 g_value_set_boolean (value, g_tuple_action_get_enabled (action));
181 break;
182
183 case PROP_STATE_TYPE:
184 g_value_set_boxed (value, g_tuple_action_get_state_type (action));
185 break;
186
187 case PROP_STATE:
188 g_value_take_variant (value, g_tuple_action_get_state (action));
189 break;
190
191 default:
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193 }
194}
195
196static void
197g_tuple_action_set_property (GObject *object,
198 guint prop_id,
199 const GValue *value,
200 GParamSpec *pspec)
201{
202 GTupleAction *tuple = G_TUPLE_ACTION (object);
203
204 switch (prop_id)
205 {
206 case PROP_NAME:
207 tuple->name = g_value_dup_string (value);
208 g_object_notify_by_pspec (object, properties[PROP_NAME]);
209 break;
210
211 case PROP_ENABLED:
212 tuple->enabled = g_value_get_boolean (value);
213 g_object_notify_by_pspec (object, properties[PROP_ENABLED]);
214 break;
215
216 case PROP_STATE:
217 g_tuple_action_set_state (tuple, g_value_get_variant (value));
218 break;
219
220 default:
221 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222 }
223}
224
225static void
226g_tuple_action_finalize (GObject *object)
227{
228 GTupleAction *tuple = G_TUPLE_ACTION (object);
229 int i;
230
231 g_free (tuple->name);
232 g_variant_type_free (tuple->type);
233
234 for (i = 0; i < tuple->n_children; i++)
235 g_variant_unref (tuple->children[i]);
236
237 g_free (tuple->children);
238
239 G_OBJECT_CLASS (g_tuple_action_parent_class)->finalize (object);
240}
241
242static void
243action_interface_init (GActionInterface *iface)
244{
245 iface->get_name = g_tuple_action_get_name;
246 iface->get_parameter_type = g_tuple_action_get_parameter_type;
247 iface->get_state_type = g_tuple_action_get_state_type;
248 iface->get_state_hint = g_tuple_action_get_state_hint;
249 iface->get_enabled = g_tuple_action_get_enabled;
250 iface->get_state = g_tuple_action_get_state;
251 iface->change_state = g_tuple_action_change_state;
252 iface->activate = g_tuple_action_activate;
253}
254
255static void
256g_tuple_action_class_init (GTupleActionClass *class)
257{
258 GObjectClass *object_class = G_OBJECT_CLASS (class);
259
260 object_class->get_property = g_tuple_action_get_property;
261 object_class->set_property = g_tuple_action_set_property;
262 object_class->finalize = g_tuple_action_finalize;
263
264 properties[PROP_NAME] = g_param_spec_string ("name",
265 "Name",
266 "The name of the action",
267 NULL,
268 G_PARAM_READWRITE |
269 G_PARAM_CONSTRUCT_ONLY |
270 G_PARAM_STATIC_STRINGS);
271
272 properties[PROP_PARAMETER_TYPE] = g_param_spec_boxed ("parameter-type",
273 "Parameter Type",
274 "The variant type passed to activate",
275 G_TYPE_VARIANT_TYPE,
276 G_PARAM_READABLE |
277 G_PARAM_STATIC_STRINGS);
278
279 properties[PROP_ENABLED] = g_param_spec_boolean ("enabled",
280 "Enabled",
281 "Whether the action can be activated",
282 TRUE,
283 G_PARAM_READWRITE |
284 G_PARAM_STATIC_STRINGS);
285
286 properties[PROP_STATE_TYPE] = g_param_spec_boxed ("state-type",
287 "State Type",
288 "The variant type of the state, must be a tuple",
289 G_TYPE_VARIANT_TYPE,
290 G_PARAM_READABLE |
291 G_PARAM_STATIC_STRINGS);
292
293 properties[PROP_STATE] = g_param_spec_variant ("state",
294 "State",
295 "The state of the action",
296 G_VARIANT_TYPE_TUPLE,
297 NULL,
298 G_PARAM_READWRITE |
299 G_PARAM_STATIC_STRINGS);
300
301 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
302
303 signal_ids[SIGNAL_ACTIVATE] = g_signal_new ("activate",
304 G_TYPE_TUPLE_ACTION,
305 G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
306 0, NULL, NULL,
307 g_cclosure_marshal_VOID__VARIANT,
308 G_TYPE_NONE, 1,
309 G_TYPE_VARIANT);
310}
311
312static void
313g_tuple_action_init (GTupleAction *action)
314{
315 action->enabled = TRUE;
316}
317
318GTupleAction *
319g_tuple_action_new (const gchar *name,
320 GVariant *initial_state)
321{
322 const GVariantType *type;
323
324 g_return_val_if_fail (name != NULL, NULL);
325 g_return_val_if_fail (initial_state != NULL, NULL);
326
327 type = g_variant_get_type (initial_state);
328 g_return_val_if_fail (g_variant_type_is_tuple (type), NULL);
329
330 return g_object_new (G_TYPE_TUPLE_ACTION,
331 "name", name,
332 "state", initial_state,
333 NULL);
334}
335
336void
337g_tuple_action_set_child (GTupleAction *action,
338 gsize index,
339 GVariant *value)
340{
341 const GVariantType *type;
342
343 g_return_if_fail (G_IS_TUPLE_ACTION (action));
344 g_return_if_fail (index < action->n_children);
345 g_return_if_fail (value != NULL);
346
347 type = g_variant_get_type (value);
348 g_return_if_fail (g_variant_is_of_type (value, type));
349
350 g_variant_unref (action->children[index]);
351 action->children[index] = g_variant_ref_sink (value);
352
353 g_object_notify_by_pspec (G_OBJECT (action), properties[PROP_STATE]);
354}
3550
=== removed file 'libmessaging-menu/gtupleaction.h'
--- libmessaging-menu/gtupleaction.h 2012-06-28 14:07:17 +0000
+++ libmessaging-menu/gtupleaction.h 1970-01-01 00:00:00 +0000
@@ -1,40 +0,0 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#ifndef __g_tuple_action_h__
21#define __g_tuple_action_h__
22
23#include <gio/gio.h>
24
25#define G_TYPE_TUPLE_ACTION (g_tuple_action_get_type ())
26#define G_TUPLE_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TUPLE_ACTION, GTupleAction))
27#define G_IS_TUPLE_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TUPLE_ACTION))
28
29typedef struct _GTupleAction GTupleAction;
30
31GType g_tuple_action_get_type (void) G_GNUC_CONST;
32
33GTupleAction * g_tuple_action_new (const gchar *name,
34 GVariant *initial_state);
35
36void g_tuple_action_set_child (GTupleAction *action,
37 gsize index,
38 GVariant *value);
39
40#endif
410
=== renamed file 'libmessaging-menu/messaging-menu.c' => 'libmessaging-menu/messaging-menu-app.c'
--- libmessaging-menu/messaging-menu.c 2013-06-07 22:15:28 +0000
+++ libmessaging-menu/messaging-menu-app.c 2013-07-12 19:50:34 +0000
@@ -17,10 +17,12 @@
17 * Lars Uebernickel <lars.uebernickel@canonical.com>17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */18 */
1919
20#include "messaging-menu.h"20#include "messaging-menu-app.h"
21#include "indicator-messages-service.h"21#include "indicator-messages-service.h"
22#include "indicator-messages-application.h"
2223
23#include <gio/gdesktopappinfo.h>24#include <gio/gdesktopappinfo.h>
25#include <string.h>
2426
25/**27/**
26 * SECTION:messaging-menu28 * SECTION:messaging-menu
@@ -102,14 +104,14 @@
102 int registered; /* -1 for unknown */104 int registered; /* -1 for unknown */
103 MessagingMenuStatus status;105 MessagingMenuStatus status;
104 gboolean status_set;106 gboolean status_set;
105 GSimpleActionGroup *source_actions;
106 GMenu *menu;
107 GDBusConnection *bus;107 GDBusConnection *bus;
108108
109 GHashTable *messages;
110 GList *sources;
111 IndicatorMessagesApplication *app_interface;
112
109 IndicatorMessagesService *messages_service;113 IndicatorMessagesService *messages_service;
110 guint watch_id;114 guint watch_id;
111 guint action_export_id;
112 guint menu_export_id;
113115
114 GCancellable *cancellable;116 GCancellable *cancellable;
115};117};
@@ -133,10 +135,61 @@
133135
134static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" };136static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" };
135137
138typedef struct
139{
140 gchar *id;
141 GIcon *icon;
142 gchar *label;
143
144 guint32 count;
145 gint64 time;
146 gchar *string;
147 gboolean draws_attention;
148} Source;
149
136static void global_status_changed (IndicatorMessagesService *service,150static void global_status_changed (IndicatorMessagesService *service,
137 const gchar *status_str,151 const gchar *status_str,
138 gpointer user_data);152 gpointer user_data);
139153
154/* in messaging-menu-message.c */
155GVariant * _messaging_menu_message_to_variant (MessagingMenuMessage *msg);
156
157static void
158source_free (gpointer data)
159{
160 Source *source = data;
161
162 if (source)
163 {
164 g_free (source->id);
165 g_clear_object (&source->icon);
166 g_free (source->label);
167 g_free (source->string);
168 g_slice_free (Source, source);
169 }
170}
171
172static GVariant *
173source_to_variant (Source *source)
174{
175 GVariant *v;
176 gchar *iconstr;
177
178 iconstr = source->icon ? g_icon_to_string (source->icon) : NULL;
179
180 v = g_variant_new ("(sssuxsb)", source->id,
181 source->label,
182 iconstr ? iconstr : "",
183 source->count,
184 source->time,
185 source->string ? source->string : "",
186 source->draws_attention);
187
188 g_free (iconstr);
189
190 return v;
191}
192
140static gchar *193static gchar *
141messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)194messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
142{195{
@@ -155,18 +208,14 @@
155}208}
156209
157static void210static void
158export_menus_and_actions (GObject *source,211messaging_menu_app_got_bus (GObject *source,
159 GAsyncResult *res,212 GAsyncResult *res,
160 gpointer user_data)213 gpointer user_data)
161{214{
162 MessagingMenuApp *app = user_data;215 MessagingMenuApp *app = user_data;
163 GError *error = NULL;216 GError *error = NULL;
164 gchar *object_path;217 gchar *object_path;
165218
166 object_path = messaging_menu_app_get_dbus_object_path (app);
167 if (!object_path)
168 return;
169
170 app->bus = g_bus_get_finish (res, &error);219 app->bus = g_bus_get_finish (res, &error);
171 if (app->bus == NULL)220 if (app->bus == NULL)
172 {221 {
@@ -175,23 +224,13 @@
175 return;224 return;
176 }225 }
177226
178 app->action_export_id = g_dbus_connection_export_action_group (app->bus,227 object_path = messaging_menu_app_get_dbus_object_path (app);
179 object_path,
180 G_ACTION_GROUP (app->source_actions),
181 &error);
182 if (!app->action_export_id)
183 {
184 g_warning ("unable to export action group: %s", error->message);
185 g_clear_error (&error);
186 }
187228
188 app->menu_export_id = g_dbus_connection_export_menu_model (app->bus,229 if (object_path &&
189 object_path,230 !g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (app->app_interface),
190 G_MENU_MODEL (app->menu),231 app->bus, object_path, &error))
191 &error);
192 if (!app->menu_export_id)
193 {232 {
194 g_warning ("unable to export menu: %s", error->message);233 g_warning ("unable to export application interface: %s", error->message);
195 g_clear_error (&error);234 g_clear_error (&error);
196 }235 }
197236
@@ -214,7 +253,7 @@
214253
215 g_bus_get (G_BUS_TYPE_SESSION,254 g_bus_get (G_BUS_TYPE_SESSION,
216 app->cancellable,255 app->cancellable,
217 export_menus_and_actions,256 messaging_menu_app_got_bus,
218 app);257 app);
219}258}
220259
@@ -248,20 +287,6 @@
248{287{
249 MessagingMenuApp *app = MESSAGING_MENU_APP (object);288 MessagingMenuApp *app = MESSAGING_MENU_APP (object);
250289
251 if (app->bus)
252 {
253 if (app->action_export_id > 0)
254 g_dbus_connection_unexport_action_group (app->bus, app->action_export_id);
255
256 if (app->menu_export_id > 0)
257 g_dbus_connection_unexport_menu_model (app->bus, app->menu_export_id);
258
259 app->action_export_id = 0;
260 app->menu_export_id = 0;
261 g_object_unref (app->bus);
262 app->bus = NULL;
263 }
264
265 if (app->watch_id > 0)290 if (app->watch_id > 0)
266 {291 {
267 g_bus_unwatch_name (app->watch_id);292 g_bus_unwatch_name (app->watch_id);
@@ -287,9 +312,14 @@
287 g_clear_object (&app->messages_service);312 g_clear_object (&app->messages_service);
288 }313 }
289314
315 g_clear_pointer (&app->messages, g_hash_table_unref);
316
317 g_list_free_full (app->sources, source_free);
318 app->sources = NULL;
319
320 g_clear_object (&app->app_interface);
290 g_clear_object (&app->appinfo);321 g_clear_object (&app->appinfo);
291 g_clear_object (&app->source_actions);322 g_clear_object (&app->bus);
292 g_clear_object (&app->menu);
293323
294 G_OBJECT_CLASS (messaging_menu_app_parent_class)->dispose (object);324 G_OBJECT_CLASS (messaging_menu_app_parent_class)->dispose (object);
295}325}
@@ -420,6 +450,168 @@
420 }450 }
421}451}
422452
453static gboolean
454messaging_menu_app_list_sources (IndicatorMessagesApplication *app_interface,
455 GDBusMethodInvocation *invocation,
456 gpointer user_data)
457{
458 MessagingMenuApp *app = user_data;
459 GVariantBuilder builder;
460 GList *it;
461
462 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssuxsb)"));
463
464 for (it = app->sources; it; it = it->next)
465 g_variant_builder_add_value (&builder, source_to_variant (it->data));
466
467 indicator_messages_application_complete_list_sources (app_interface,
468 invocation,
469 g_variant_builder_end (&builder));
470
471 return TRUE;
472}
473
474static gint
475compare_source_id (gconstpointer a,
476 gconstpointer b)
477{
478 const Source *source = a;
479 const gchar *id = b;
480
481 return strcmp (source->id, id);
482}
483
484static gboolean
485messaging_menu_app_remove_source_internal (MessagingMenuApp *app,
486 const gchar *source_id)
487{
488 GList *node;
489
490 node = g_list_find_custom (app->sources, source_id, compare_source_id);
491 if (node)
492 {
493 source_free (node->data);
494 app->sources = g_list_delete_link (app->sources, node);
495 return TRUE;
496 }
497
498 return FALSE;
499}
500
501static gboolean
502messaging_menu_app_remove_message_internal (MessagingMenuApp *app,
503 const gchar *message_id)
504{
505 return g_hash_table_remove (app->messages, message_id);
506}
507
508static gboolean
509messaging_menu_app_activate_source (IndicatorMessagesApplication *app_interface,
510 GDBusMethodInvocation *invocation,
511 const gchar *source_id,
512 gpointer user_data)
513{
514 MessagingMenuApp *app = user_data;
515 GQuark q = g_quark_from_string (source_id);
516
517 /* Activate implies removing the source, no need for SourceRemoved */
518 if (messaging_menu_app_remove_source_internal (app, source_id))
519 g_signal_emit (app, signals[ACTIVATE_SOURCE], q, source_id);
520
521 indicator_messages_application_complete_activate_source (app_interface, invocation);
522
523 return TRUE;
524}
525
526static gboolean
527messaging_menu_app_list_messages (IndicatorMessagesApplication *app_interface,
528 GDBusMethodInvocation *invocation,
529 gpointer user_data)
530{
531 MessagingMenuApp *app = user_data;
532 GVariantBuilder builder;
533 GHashTableIter iter;
534 MessagingMenuMessage *message;
535
536 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxaa{sv}b)"));
537
538 g_hash_table_iter_init (&iter, app->messages);
539 while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
540 g_variant_builder_add_value (&builder, _messaging_menu_message_to_variant (message));
541
542 indicator_messages_application_complete_list_messages (app_interface,
543 invocation,
544 g_variant_builder_end (&builder));
545
546 return TRUE;
547}
548
549static gboolean
550messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface,
551 GDBusMethodInvocation *invocation,
552 const gchar *message_id,
553 const gchar *action_id,
554 GVariant *params,
555 gpointer user_data)
556{
557 MessagingMenuApp *app = user_data;
558 MessagingMenuMessage *msg;
559
560 msg = g_hash_table_lookup (app->messages, message_id);
561 if (msg)
562 {
563 if (*action_id)
564 {
565 gchar *signal;
566
567 signal = g_strconcat ("activate::", action_id, NULL);
568
569 if (g_variant_n_children (params))
570 {
571 GVariant *param;
572
573 g_variant_get_child (params, 0, "v", &param);
574 g_signal_emit_by_name (msg, signal, action_id, param);
575
576 g_variant_unref (param);
577 }
578 else
579 g_signal_emit_by_name (msg, signal, action_id, NULL);
580
581 g_free (signal);
582 }
583 else
584 g_signal_emit_by_name (msg, "activate", NULL, NULL);
585
586
587 /* Activate implies removing the message, no need for MessageRemoved */
588 messaging_menu_app_remove_message_internal (app, message_id);
589 }
590
591 indicator_messages_application_complete_activate_message (app_interface, invocation);
592
593 return TRUE;
594}
595
596static gboolean
597messaging_menu_app_dismiss (IndicatorMessagesApplication *app_interface,
598 GDBusMethodInvocation *invocation,
599 const gchar * const *sources,
600 const gchar * const *messages,
601 gpointer user_data)
602{
603 MessagingMenuApp *app = user_data;
604 const gchar * const *it;
605
606 for (it = sources; *it; it++)
607 messaging_menu_app_remove_source_internal (app, *it);
608
609 for (it = messages; *it; it++)
610 messaging_menu_app_remove_message_internal (app, *it);
611
612 return TRUE;
613}
614
423static void615static void
424messaging_menu_app_init (MessagingMenuApp *app)616messaging_menu_app_init (MessagingMenuApp *app)
425{617{
@@ -427,15 +619,21 @@
427 app->status_set = FALSE;619 app->status_set = FALSE;
428 app->bus = NULL;620 app->bus = NULL;
429621
430 app->action_export_id = 0;622 app->cancellable = g_cancellable_new ();
431 app->menu_export_id = 0;623
432624 app->app_interface = indicator_messages_application_skeleton_new ();
433 app->cancellable = g_cancellable_new ();625 g_signal_connect (app->app_interface, "handle-list-sources",
434626 G_CALLBACK (messaging_menu_app_list_sources), app);
435 app->source_actions = g_simple_action_group_new ();627 g_signal_connect (app->app_interface, "handle-activate-source",
436 app->menu = g_menu_new ();628 G_CALLBACK (messaging_menu_app_activate_source), app);
437629 g_signal_connect (app->app_interface, "handle-list-messages",
438 app->cancellable = g_cancellable_new ();630 G_CALLBACK (messaging_menu_app_list_messages), app);
631 g_signal_connect (app->app_interface, "handle-activate-message",
632 G_CALLBACK (messaging_menu_app_activate_message), app);
633 g_signal_connect (app->app_interface, "handle-dismiss",
634 G_CALLBACK (messaging_menu_app_dismiss), app);
635
636 app->messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
439637
440 app->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,638 app->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
441 "com.canonical.indicator.messages",639 "com.canonical.indicator.messages",
@@ -608,40 +806,61 @@
608 g_signal_emit (app, signals[STATUS_CHANGED], 0, status);806 g_signal_emit (app, signals[STATUS_CHANGED], 0, status);
609}807}
610808
611static void809static Source *
612source_action_activated (GSimpleAction *action,810messaging_menu_app_lookup_source (MessagingMenuApp *app,
613 GVariant *parameter,811 const gchar *id)
614 gpointer user_data)812{
615{813 GList *node;
616 MessagingMenuApp *app = user_data;814
617 const gchar *name = g_action_get_name (G_ACTION (action));815 node = g_list_find_custom (app->sources, id, compare_source_id);
618 GQuark q = g_quark_from_string (name);816
619817 return node ? node->data : NULL;
620 messaging_menu_app_remove_source (app, name);818}
621819
622 g_signal_emit (app, signals[ACTIVATE_SOURCE], q, name);820static Source *
623}821messaging_menu_app_get_source (MessagingMenuApp *app,
624822 const gchar *id)
625static void823{
626messaging_menu_app_insert_source_action (MessagingMenuApp *app,824 Source *source;
627 gint position,825
628 const gchar *id,826 source = messaging_menu_app_lookup_source (app, id);
629 GIcon *icon,827 if (!source)
630 const gchar *label,828 g_warning ("a source with id '%s' doesn't exist", id);
631 GVariant *state)829
632{830 return source;
633 GSimpleAction *action;831}
634 GMenuItem *menuitem;832
833static void
834messaging_menu_app_notify_source_changed (MessagingMenuApp *app,
835 Source *source)
836{
837 indicator_messages_application_emit_source_changed (app->app_interface,
838 source_to_variant (source));
839}
840
841static void
842messaging_menu_app_insert_source_internal (MessagingMenuApp *app,
843 gint position,
844 const gchar *id,
845 GIcon *icon,
846 const gchar *label,
847 guint count,
848 gint64 time,
849 const gchar *string)
850{
851 Source *source;
635852
636 g_return_if_fail (MESSAGING_MENU_IS_APP (app));853 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
637 g_return_if_fail (id != NULL);854 g_return_if_fail (id != NULL);
855 g_return_if_fail (label != NULL);
638856
639 if (g_simple_action_group_lookup (app->source_actions, id))857 if (messaging_menu_app_lookup_source (app, id))
640 {858 {
641 g_warning ("a source with id '%s' already exists", id);859 g_warning ("a source with id '%s' already exists", id);
642 return;860 return;
643 }861 }
644862
863<<<<<<< TREE
645 action = g_simple_action_new_stateful (id, NULL, state);864 action = g_simple_action_new_stateful (id, NULL, state);
646 g_signal_connect (action, "activate",865 g_signal_connect (action, "activate",
647 G_CALLBACK (source_action_activated), app);866 G_CALLBACK (source_action_activated), app);
@@ -651,7 +870,13 @@
651 menuitem = g_menu_item_new (label, NULL);870 menuitem = g_menu_item_new (label, NULL);
652 g_menu_item_set_action_and_target_value (menuitem, id, NULL);871 g_menu_item_set_action_and_target_value (menuitem, id, NULL);
653 g_menu_item_set_attribute (menuitem, "x-canonical-type", "s", "ImSourceMenuItem");872 g_menu_item_set_attribute (menuitem, "x-canonical-type", "s", "ImSourceMenuItem");
873=======
874 source = g_slice_new0 (Source);
875 source->id = g_strdup (id);
876 source->label = g_strdup (label);
877>>>>>>> MERGE-SOURCE
654 if (icon)878 if (icon)
879<<<<<<< TREE
655 {880 {
656 gchar *iconstr = g_icon_to_string (icon);881 gchar *iconstr = g_icon_to_string (icon);
657 g_menu_item_set_attribute (menuitem, "x-canonical-icon", "s", iconstr);882 g_menu_item_set_attribute (menuitem, "x-canonical-icon", "s", iconstr);
@@ -726,6 +951,17 @@
726 g_simple_action_set_state (action, new_state);951 g_simple_action_set_state (action, new_state);
727952
728 g_variant_unref (state);953 g_variant_unref (state);
954=======
955 source->icon = g_object_ref (icon);
956 source->count = count;
957 source->time = time;
958 source->string = g_strdup (string);
959 app->sources = g_list_insert (app->sources, source, position);
960
961 indicator_messages_application_emit_source_added (app->app_interface,
962 position,
963 source_to_variant (source));
964>>>>>>> MERGE-SOURCE
729}965}
730966
731/**967/**
@@ -802,8 +1038,7 @@
802 const gchar *label,1038 const gchar *label,
803 guint count)1039 guint count)
804{1040{
805 messaging_menu_app_insert_source_action (app, position, id, icon, label,1041 messaging_menu_app_insert_source_internal (app, position, id, icon, label, count, 0, "");
806 g_variant_new ("(uxsb)", count, 0, "", FALSE));
807}1042}
8081043
809/**1044/**
@@ -857,8 +1092,7 @@
857 const gchar *label,1092 const gchar *label,
858 gint64 time)1093 gint64 time)
859{1094{
860 messaging_menu_app_insert_source_action (app, position, id, icon, label,1095 messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, time, "");
861 g_variant_new ("(uxsb)", 0, time, "", FALSE));
862}1096}
8631097
864/**1098/**
@@ -914,8 +1148,7 @@
914 const gchar *label,1148 const gchar *label,
915 const gchar *str)1149 const gchar *str)
916{1150{
917 messaging_menu_app_insert_source_action (app, position, id, icon, label,1151 messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, 0, str);
918 g_variant_new ("(uxsb)", 0, 0, str, FALSE));
919}1152}
9201153
921/**1154/**
@@ -955,34 +1188,11 @@
955messaging_menu_app_remove_source (MessagingMenuApp *app,1188messaging_menu_app_remove_source (MessagingMenuApp *app,
956 const gchar *source_id)1189 const gchar *source_id)
957{1190{
958 int n_items;
959 int i;
960
961 g_return_if_fail (MESSAGING_MENU_IS_APP (app));1191 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
962 g_return_if_fail (source_id != NULL);1192 g_return_if_fail (source_id != NULL);
9631193
964 if (g_simple_action_group_lookup (app->source_actions, source_id) == NULL)1194 if (messaging_menu_app_remove_source_internal (app, source_id))
965 return;1195 indicator_messages_application_emit_source_removed (app->app_interface, source_id);
966
967 n_items = g_menu_model_get_n_items (G_MENU_MODEL (app->menu));
968 for (i = 0; i < n_items; i++)
969 {
970 gchar *action;
971
972 if (g_menu_model_get_item_attribute (G_MENU_MODEL (app->menu), i,
973 "action", "s", &action))
974 {
975 if (!g_strcmp0 (action, source_id))
976 {
977 g_menu_remove (app->menu, i);
978 break;
979 }
980
981 g_free (action);
982 }
983 }
984
985 g_simple_action_group_remove (app->source_actions, source_id);
986}1196}
9871197
988/**1198/**
@@ -999,46 +1209,7 @@
999 g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), FALSE);1209 g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), FALSE);
1000 g_return_val_if_fail (source_id != NULL, FALSE);1210 g_return_val_if_fail (source_id != NULL, FALSE);
10011211
1002 return g_simple_action_group_lookup (app->source_actions, source_id) != NULL;1212 return messaging_menu_app_lookup_source (app, source_id) != NULL;
1003}
1004
1005static GMenuItem *
1006g_menu_find_item_with_action (GMenu *menu,
1007 const gchar *action,
1008 gint *out_pos)
1009{
1010 gint i;
1011 gint n_elements;
1012 GMenuItem *item = NULL;
1013
1014 n_elements = g_menu_model_get_n_items (G_MENU_MODEL (menu));
1015
1016 for (i = 0; i < n_elements && item == NULL; i++)
1017 {
1018 GVariant *attr;
1019
1020 item = g_menu_item_new_from_model (G_MENU_MODEL (menu), i);
1021 attr = g_menu_item_get_attribute_value (item, G_MENU_ATTRIBUTE_ACTION, G_VARIANT_TYPE_STRING);
1022
1023 if (!g_str_equal (action, g_variant_get_string (attr, NULL)))
1024 g_clear_object (&item);
1025
1026 g_variant_unref (attr);
1027 }
1028
1029 if (item && out_pos)
1030 *out_pos = i - 1;
1031
1032 return item;
1033}
1034
1035static void
1036g_menu_replace_item (GMenu *menu,
1037 gint pos,
1038 GMenuItem *item)
1039{
1040 g_menu_remove (menu, pos);
1041 g_menu_insert_item (menu, pos, item);
1042}1213}
10431214
1044/**1215/**
@@ -1054,21 +1225,19 @@
1054 const gchar *source_id,1225 const gchar *source_id,
1055 const gchar *label)1226 const gchar *label)
1056{1227{
1057 gint pos;1228 Source *source;
1058 GMenuItem *item;
10591229
1060 g_return_if_fail (MESSAGING_MENU_IS_APP (app));1230 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1061 g_return_if_fail (source_id != NULL);1231 g_return_if_fail (source_id != NULL);
1062 g_return_if_fail (label != NULL);1232 g_return_if_fail (label != NULL);
10631233
1064 item = g_menu_find_item_with_action (app->menu, source_id, &pos);1234 source = messaging_menu_app_get_source (app, source_id);
1065 if (item == NULL)1235 if (source)
1066 return;1236 {
10671237 g_free (source->label);
1068 g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_LABEL, "s", label);1238 source->label = g_strdup (label);
1069 g_menu_replace_item (app->menu, pos, item);1239 messaging_menu_app_notify_source_changed (app, source);
10701240 }
1071 g_object_unref (item);
1072}1241}
10731242
1074/**1243/**
@@ -1084,33 +1253,19 @@
1084 const gchar *source_id,1253 const gchar *source_id,
1085 GIcon *icon)1254 GIcon *icon)
1086{1255{
1087 gint pos;1256 Source *source;
1088 GMenuItem *item;
10891257
1090 g_return_if_fail (MESSAGING_MENU_IS_APP (app));1258 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1091 g_return_if_fail (source_id != NULL);1259 g_return_if_fail (source_id != NULL);
10921260
1093 item = g_menu_find_item_with_action (app->menu, source_id, &pos);1261 source = messaging_menu_app_get_source (app, source_id);
1094 if (item == NULL)1262 if (source)
1095 return;1263 {
10961264 g_clear_object (&source->icon);
1097 if (icon)1265 if (icon)
1098 {1266 source->icon = g_object_ref (icon);
1099 gchar *iconstr;1267 messaging_menu_app_notify_source_changed (app, source);
11001268 }
1101 iconstr = g_icon_to_string (icon);
1102 g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr);
1103
1104 g_free (iconstr);
1105 }
1106 else
1107 {
1108 g_menu_item_set_attribute_value (item, "x-canonical-icon", NULL);
1109 }
1110
1111 g_menu_replace_item (app->menu, pos, item);
1112
1113 g_object_unref (item);
1114}1269}
11151270
1116/**1271/**
@@ -1125,7 +1280,17 @@
1125 const gchar *source_id,1280 const gchar *source_id,
1126 guint count)1281 guint count)
1127{1282{
1128 messaging_menu_app_set_source_action (app, source_id, count, 0, "");1283 Source *source;
1284
1285 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1286 g_return_if_fail (source_id != NULL);
1287
1288 source = messaging_menu_app_get_source (app, source_id);
1289 if (source)
1290 {
1291 source->count = count;
1292 messaging_menu_app_notify_source_changed (app, source);
1293 }
1129}1294}
11301295
1131/**1296/**
@@ -1141,7 +1306,17 @@
1141 const gchar *source_id,1306 const gchar *source_id,
1142 gint64 time)1307 gint64 time)
1143{1308{
1144 messaging_menu_app_set_source_action (app, source_id, 0, time, "");1309 Source *source;
1310
1311 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1312 g_return_if_fail (source_id != NULL);
1313
1314 source = messaging_menu_app_get_source (app, source_id);
1315 if (source)
1316 {
1317 source->time = time;
1318 messaging_menu_app_notify_source_changed (app, source);
1319 }
1145}1320}
11461321
1147/**1322/**
@@ -1157,7 +1332,18 @@
1157 const gchar *source_id,1332 const gchar *source_id,
1158 const gchar *str)1333 const gchar *str)
1159{1334{
1160 messaging_menu_app_set_source_action (app, source_id, 0, 0, str);1335 Source *source;
1336
1337 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1338 g_return_if_fail (source_id != NULL);
1339
1340 source = messaging_menu_app_get_source (app, source_id);
1341 if (source)
1342 {
1343 g_free (source->string);
1344 source->string = g_strdup (str);
1345 messaging_menu_app_notify_source_changed (app, source);
1346 }
1161}1347}
11621348
1163/**1349/**
@@ -1175,7 +1361,17 @@
1175messaging_menu_app_draw_attention (MessagingMenuApp *app,1361messaging_menu_app_draw_attention (MessagingMenuApp *app,
1176 const gchar *source_id)1362 const gchar *source_id)
1177{1363{
1178 messaging_menu_app_set_draws_attention (app, source_id, TRUE);1364 Source *source;
1365
1366 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1367 g_return_if_fail (source_id != NULL);
1368
1369 source = messaging_menu_app_get_source (app, source_id);
1370 if (source)
1371 {
1372 source->draws_attention = TRUE;
1373 messaging_menu_app_notify_source_changed (app, source);
1374 }
1179}1375}
11801376
1181/**1377/**
@@ -1196,5 +1392,135 @@
1196messaging_menu_app_remove_attention (MessagingMenuApp *app,1392messaging_menu_app_remove_attention (MessagingMenuApp *app,
1197 const gchar *source_id)1393 const gchar *source_id)
1198{1394{
1395<<<<<<< TREE
1199 messaging_menu_app_set_draws_attention (app, source_id, FALSE);1396 messaging_menu_app_set_draws_attention (app, source_id, FALSE);
1397=======
1398 Source *source;
1399
1400 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1401 g_return_if_fail (source_id != NULL);
1402
1403 source = messaging_menu_app_get_source (app, source_id);
1404 if (source)
1405 {
1406 source->draws_attention = FALSE;
1407 messaging_menu_app_notify_source_changed (app, source);
1408 }
1409}
1410
1411/**
1412 * messaging_menu_app_append_message:
1413 * @app: a #MessagingMenuApp
1414 * @msg: the #MessagingMenuMessage to append
1415 * @source_id: (allow-none): the source id to which @msg is added, or NULL
1416 * @notify: whether a notification bubble should be shown for this
1417 * message
1418 *
1419 * Appends @msg to the source with id @source_id of @app. The messaging
1420 * menu might not display this message immediately if other messages are
1421 * queued before this one.
1422 *
1423 * If @source_id has a count associated with it, that count will be
1424 * increased by one.
1425 *
1426 * If @source_id is %NULL, @msg won't be associated with a source.
1427 */
1428void
1429messaging_menu_app_append_message (MessagingMenuApp *app,
1430 MessagingMenuMessage *msg,
1431 const gchar *source_id,
1432 gboolean notify)
1433{
1434 const gchar *id;
1435
1436 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1437 g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
1438
1439 id = messaging_menu_message_get_id (msg);
1440
1441 if (g_hash_table_lookup (app->messages, id))
1442 {
1443 g_warning ("a message with id '%s' already exists", id);
1444 return;
1445 }
1446
1447 g_hash_table_insert (app->messages, g_strdup (id), g_object_ref (msg));
1448 indicator_messages_application_emit_message_added (app->app_interface,
1449 _messaging_menu_message_to_variant (msg));
1450
1451 if (source_id)
1452 {
1453 Source *source;
1454
1455 source = messaging_menu_app_get_source (app, source_id);
1456 if (source && source->count >= 0)
1457 {
1458 source->count++;
1459 messaging_menu_app_notify_source_changed (app, source);
1460 }
1461 }
1462}
1463
1464/**
1465 * messaging_menu_app_get_message:
1466 * @app: a #MessagingMenuApp
1467 * @id: id of the message to retrieve
1468 *
1469 * Retrieves the message with @id, that was added with
1470 * messaging_menu_app_append_message().
1471 *
1472 * Returns: (transfer none) (allow-none): the #MessagingMenuApp with
1473 * @id, or %NULL
1474 */
1475MessagingMenuMessage *
1476messaging_menu_app_get_message (MessagingMenuApp *app,
1477 const gchar *id)
1478{
1479 g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), NULL);
1480 g_return_val_if_fail (id != NULL, NULL);
1481
1482 return g_hash_table_lookup (app->messages, id);
1483}
1484
1485/**
1486 * messaging_menu_app_remove_message:
1487 * @app: a #MessagingMenuApp
1488 * @msg: the #MessagingMenuMessage to remove
1489 *
1490 * Removes @msg from @app.
1491 *
1492 * If @source_id has a count associated with it, that count will be
1493 * decreased by one.
1494 */
1495void
1496messaging_menu_app_remove_message (MessagingMenuApp *app,
1497 MessagingMenuMessage *msg)
1498{
1499 /* take a ref of @msg here to make sure the pointer returned by
1500 * _get_id() is valid for the duration of remove_message_by_id. */
1501 g_object_ref (msg);
1502 messaging_menu_app_remove_message_by_id (app, messaging_menu_message_get_id (msg));
1503 g_object_unref (msg);
1504}
1505
1506/**
1507 * messaging_menu_app_remove_message_by_id:
1508 * @app: a #MessagingMenuApp
1509 * @id: the unique id of @msg
1510 *
1511 * Removes the message with the id @id from @app.
1512 *
1513 * If @source_id has a count associated with it, that count will be
1514 * decreased by one.
1515 */
1516void
1517messaging_menu_app_remove_message_by_id (MessagingMenuApp *app,
1518 const gchar *id)
1519{
1520 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
1521 g_return_if_fail (id != NULL);
1522
1523 if (messaging_menu_app_remove_message_internal (app, id))
1524 indicator_messages_application_emit_message_removed (app->app_interface, id);
1525>>>>>>> MERGE-SOURCE
1200}1526}
12011527
=== renamed file 'libmessaging-menu/messaging-menu.h' => 'libmessaging-menu/messaging-menu-app.h'
--- libmessaging-menu/messaging-menu.h 2012-08-31 17:19:21 +0000
+++ libmessaging-menu/messaging-menu-app.h 2013-07-12 19:50:34 +0000
@@ -17,10 +17,11 @@
17 * Lars Uebernickel <lars.uebernickel@canonical.com>17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */18 */
1919
20#ifndef __messaging_menu_h__20#ifndef __messaging_menu_app_h__
21#define __messaging_menu_h__21#define __messaging_menu_app_h__
2222
23#include <gio/gio.h>23#include <gio/gio.h>
24#include "messaging-menu-message.h"
2425
25G_BEGIN_DECLS26G_BEGIN_DECLS
2627
@@ -143,6 +144,20 @@
143void messaging_menu_app_remove_attention (MessagingMenuApp *app,144void messaging_menu_app_remove_attention (MessagingMenuApp *app,
144 const gchar *source_id);145 const gchar *source_id);
145146
147void messaging_menu_app_append_message (MessagingMenuApp *app,
148 MessagingMenuMessage *msg,
149 const gchar *source_id,
150 gboolean notify);
151
152MessagingMenuMessage * messaging_menu_app_get_message (MessagingMenuApp *app,
153 const gchar *id);
154
155void messaging_menu_app_remove_message (MessagingMenuApp *app,
156 MessagingMenuMessage *msg);
157
158void messaging_menu_app_remove_message_by_id (MessagingMenuApp *app,
159 const gchar *id);
160
146G_END_DECLS161G_END_DECLS
147162
148#endif163#endif
149164
=== added file 'libmessaging-menu/messaging-menu-message.c'
--- libmessaging-menu/messaging-menu-message.c 1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu-message.c 2013-07-12 19:50:34 +0000
@@ -0,0 +1,547 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#include "messaging-menu-message.h"
21
22typedef GObjectClass MessagingMenuMessageClass;
23
24struct _MessagingMenuMessage
25{
26 GObject parent;
27
28 gchar *id;
29 GIcon *icon;
30 gchar *title;
31 gchar *subtitle;
32 gchar *body;
33 gint64 time;
34 gboolean draws_attention;
35
36 GSList *actions;
37};
38
39G_DEFINE_TYPE (MessagingMenuMessage, messaging_menu_message, G_TYPE_OBJECT);
40
41enum
42{
43 PROP_0,
44 PROP_ID,
45 PROP_ICON,
46 PROP_TITLE,
47 PROP_SUBTITLE,
48 PROP_BODY,
49 PROP_TIME,
50 PROP_DRAWS_ATTENTION,
51 NUM_PROPERTIES
52};
53
54static GParamSpec *properties[NUM_PROPERTIES];
55
56typedef struct
57{
58 gchar *id;
59 gchar *label;
60 GVariantType *parameter_type;
61 GVariant *parameter_hint;
62} Action;
63
64static void
65action_free (gpointer data)
66{
67 Action *action = data;
68
69 g_free (action->id);
70 g_free (action->label);
71
72 if (action->parameter_type)
73 g_variant_type_free (action->parameter_type);
74
75 if (action->parameter_hint)
76 g_variant_unref (action->parameter_hint);
77
78 g_slice_free (Action, action);
79}
80
81static void
82messaging_menu_message_dispose (GObject *object)
83{
84 MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
85
86 g_clear_object (&msg->icon);
87
88 G_OBJECT_CLASS (messaging_menu_message_parent_class)->dispose (object);
89}
90
91static void
92messaging_menu_message_finalize (GObject *object)
93{
94 MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
95
96 g_free (msg->id);
97 g_free (msg->title);
98 g_free (msg->subtitle);
99 g_free (msg->body);
100
101 g_slist_free_full (msg->actions, action_free);
102 msg->actions = NULL;
103
104 G_OBJECT_CLASS (messaging_menu_message_parent_class)->finalize (object);
105}
106
107static void
108messaging_menu_message_get_property (GObject *object,
109 guint property_id,
110 GValue *value,
111 GParamSpec *pspec)
112{
113 MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
114
115 switch (property_id)
116 {
117 case PROP_ID:
118 g_value_set_string (value, msg->id);
119 break;
120
121 case PROP_ICON:
122 g_value_set_object (value, msg->icon);
123 break;
124
125 case PROP_TITLE:
126 g_value_set_string (value, msg->title);
127 break;
128
129 case PROP_SUBTITLE:
130 g_value_set_string (value, msg->subtitle);
131 break;
132
133 case PROP_BODY:
134 g_value_set_string (value, msg->body);
135
136 case PROP_TIME:
137 g_value_set_int64 (value, msg->time);
138 break;
139
140 case PROP_DRAWS_ATTENTION:
141 g_value_set_boolean (value, msg->draws_attention);
142 break;
143
144 default:
145 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
146 }
147}
148
149static void
150messaging_menu_message_set_property (GObject *object,
151 guint property_id,
152 const GValue *value,
153 GParamSpec *pspec)
154{
155 MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
156
157 switch (property_id)
158 {
159 case PROP_ID:
160 msg->id = g_value_dup_string (value);
161 break;
162
163 case PROP_ICON:
164 msg->icon = g_value_dup_object (value);
165 break;
166
167 case PROP_TITLE:
168 msg->title = g_value_dup_string (value);
169 break;
170
171 case PROP_SUBTITLE:
172 msg->subtitle = g_value_dup_string (value);
173 break;
174
175 case PROP_BODY:
176 msg->body = g_value_dup_string (value);
177
178 case PROP_TIME:
179 msg->time = g_value_get_int64 (value);
180 break;
181
182 case PROP_DRAWS_ATTENTION:
183 messaging_menu_message_set_draws_attention (msg, g_value_get_boolean (value));
184 break;
185
186 default:
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
188 }
189}
190
191static void
192messaging_menu_message_class_init (MessagingMenuMessageClass *klass)
193{
194 GObjectClass *object_class = G_OBJECT_CLASS (klass);
195
196 object_class->dispose = messaging_menu_message_dispose;
197 object_class->finalize = messaging_menu_message_finalize;
198 object_class->get_property = messaging_menu_message_get_property;
199 object_class->set_property = messaging_menu_message_set_property;
200
201 properties[PROP_ID] = g_param_spec_string ("id", "Id",
202 "Unique id of the message",
203 NULL,
204 G_PARAM_CONSTRUCT_ONLY |
205 G_PARAM_READWRITE |
206 G_PARAM_STATIC_STRINGS);
207
208 properties[PROP_ICON] = g_param_spec_object ("icon", "Icon",
209 "Icon of the message",
210 G_TYPE_ICON,
211 G_PARAM_CONSTRUCT_ONLY |
212 G_PARAM_READWRITE |
213 G_PARAM_STATIC_STRINGS);
214
215 properties[PROP_TITLE] = g_param_spec_string ("title", "Title",
216 "Title of the message",
217 NULL,
218 G_PARAM_CONSTRUCT_ONLY |
219 G_PARAM_READWRITE |
220 G_PARAM_STATIC_STRINGS);
221
222 properties[PROP_SUBTITLE] = g_param_spec_string ("subtitle", "Subtitle",
223 "Subtitle of the message",
224 NULL,
225 G_PARAM_CONSTRUCT_ONLY |
226 G_PARAM_READWRITE |
227 G_PARAM_STATIC_STRINGS);
228
229 properties[PROP_BODY] = g_param_spec_string ("body", "Body",
230 "First lines of the body of the message",
231 NULL,
232 G_PARAM_CONSTRUCT_ONLY |
233 G_PARAM_READWRITE |
234 G_PARAM_STATIC_STRINGS);
235
236 properties[PROP_TIME] = g_param_spec_int64 ("time", "Time",
237 "Time the message was sent, in microseconds", 0, G_MAXINT64, 0,
238 G_PARAM_CONSTRUCT_ONLY |
239 G_PARAM_READWRITE |
240 G_PARAM_STATIC_STRINGS);
241
242 properties[PROP_DRAWS_ATTENTION] = g_param_spec_boolean ("draws-attention", "Draws attention",
243 "Whether the message should draw attention",
244 FALSE,
245 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
246
247 g_object_class_install_properties (klass, NUM_PROPERTIES, properties);
248
249 /**
250 * MessagingMenuMessage::activate:
251 * @msg: the #MessagingMenuMessage
252 * @action: (allow-none): the id of activated action, or %NULL
253 * @parameter: (allow-none): activation parameter, or %NULL
254 *
255 * Emitted when the user has activated the message. The message is
256 * immediately removed from the application's menu, handlers of this
257 * signal do not need to call messaging_menu_app_remove_message().
258 */
259 g_signal_new ("activate",
260 MESSAGING_MENU_TYPE_MESSAGE,
261 G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
262 0,
263 NULL, NULL,
264 g_cclosure_marshal_generic,
265 G_TYPE_NONE, 2,
266 G_TYPE_STRING,
267 G_TYPE_VARIANT);
268}
269
270static void
271messaging_menu_message_init (MessagingMenuMessage *self)
272{
273}
274
275/**
276 * messaging_menu_message_new:
277 * @id: unique id of the message
278 * @icon: (transfer full) (allow-none): a #GIcon representing the message
279 * @title: the title of the message
280 * @subtitle: (allow-none): the subtitle of the message
281 * @body: (allow-none): the message body
282 * @time: the time the message was received
283 *
284 * Creates a new #MessagingMenuMessage.
285 *
286 * Returns: (transfer full): a new #MessagingMenuMessage
287 */
288MessagingMenuMessage *
289messaging_menu_message_new (const gchar *id,
290 GIcon *icon,
291 const gchar *title,
292 const gchar *subtitle,
293 const gchar *body,
294 gint64 time)
295{
296 g_return_val_if_fail (id != NULL, NULL);
297 g_return_val_if_fail (title != NULL, NULL);
298
299 return g_object_new (MESSAGING_MENU_TYPE_MESSAGE,
300 "id", id,
301 "icon", icon,
302 "title", title,
303 "subtitle", subtitle,
304 "body", body,
305 "time", time,
306 NULL);
307}
308
309/**
310 * messaging_menu_message_get_id:
311 * @msg: a #MessagingMenuMessage
312 *
313 * Returns: the unique id of @msg
314 */
315const gchar *
316messaging_menu_message_get_id (MessagingMenuMessage *msg)
317{
318 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
319
320 return msg->id;
321}
322
323/**
324 * messaging_menu_message_get_icon:
325 * @msg: a #MessagingMenuMessage
326 *
327 * Returns: (transfer none): the icon of @msg
328 */
329GIcon *
330messaging_menu_message_get_icon (MessagingMenuMessage *msg)
331{
332 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
333
334 return msg->icon;
335}
336
337/**
338 * messaging_menu_message_get_title:
339 * @msg: a #MessagingMenuMessage
340 *
341 * Returns: the title of @msg
342 */
343const gchar *
344messaging_menu_message_get_title (MessagingMenuMessage *msg)
345{
346 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
347
348 return msg->title;
349}
350
351/**
352 * messaging_menu_message_get_subtitle:
353 * @msg: a #MessagingMenuMessage
354 *
355 * Returns: the subtitle of @msg
356 */
357const gchar *
358messaging_menu_message_get_subtitle (MessagingMenuMessage *msg)
359{
360 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
361
362 return msg->subtitle;
363}
364
365/**
366 * messaging_menu_message_get_body:
367 * @msg: a #MessagingMenuMessage
368 *
369 * Returns: the body of @msg
370 */
371const gchar *
372messaging_menu_message_get_body (MessagingMenuMessage *msg)
373{
374 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
375
376 return msg->body;
377}
378
379/**
380 * messaging_menu_message_get_time:
381 * @msg: a #MessagingMenuMessage
382 *
383 * Returns: the time at which @msg was received
384 */
385gint64
386messaging_menu_message_get_time (MessagingMenuMessage *msg)
387{
388 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), 0);
389
390 return msg->time;
391}
392
393/**
394 * messaging_menu_message_get_draws_attention:
395 * @msg: a #MessagingMenuMessage
396 *
397 * Returns: whether @msg is drawing attention
398 */
399gboolean
400messaging_menu_message_get_draws_attention (MessagingMenuMessage *msg)
401{
402 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), FALSE);
403
404 return msg->draws_attention;
405}
406
407/**
408 * messaging_menu_message_set_draws_attention:
409 * @msg: a #MessagingMenuMessage
410 * @draws_attention: whether @msg should draw attention
411 *
412 * Sets whether @msg is drawing attention.
413 */
414void
415messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
416 gboolean draws_attention)
417{
418 g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
419
420 msg->draws_attention = draws_attention;
421 g_object_notify_by_pspec (G_OBJECT (msg), properties[PROP_DRAWS_ATTENTION]);
422}
423
424/**
425 * messaging_menu_message_add_action:
426 * @msg: a #MessagingMenuMessage
427 * @id: unique id of the action
428 * @label: (allow-none): label of the action
429 * @parameter_type: (allow-none): a #GVariantType
430 * @parameter_hint: (allow-none): a #GVariant suggesting a valid range
431 * for parameters
432 *
433 * Adds an action with @id and @label to @message. Actions are an
434 * alternative way for users to activate a message. Note that messages
435 * can still be activated without an action.
436 *
437 * If @parameter_type is non-%NULL, the action is able to receive user
438 * input in addition to simply activating the action. Currently, only
439 * string parameters are supported.
440 *
441 * A list of predefined parameters can be supplied as a #GVariant array
442 * of @parameter_type in @parameter_hint. If @parameter_hint is
443 * floating, it will be consumed.
444 *
445 * It is recommended to add at most two actions to a message.
446 */
447void
448messaging_menu_message_add_action (MessagingMenuMessage *msg,
449 const gchar *id,
450 const gchar *label,
451 const GVariantType *parameter_type,
452 GVariant *parameter_hint)
453{
454 Action *action;
455
456 g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
457 g_return_if_fail (id != NULL);
458
459 action = g_slice_new (Action);
460 action->id = g_strdup (id);
461 action->label = g_strdup (label);
462 action->parameter_type = parameter_type ? g_variant_type_copy (parameter_type) : NULL;
463 action->parameter_hint = parameter_hint ? g_variant_ref_sink (parameter_hint) : NULL;
464
465 msg->actions = g_slist_append (msg->actions, action);
466}
467
468static GVariant *
469action_to_variant (Action *action)
470{
471 GVariantBuilder builder;
472
473 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
474
475 g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (action->id));
476
477 if (action->label)
478 g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (action->label));
479
480 if (action->parameter_type)
481 {
482 gchar *type = g_variant_type_dup_string (action->parameter_type);
483 g_variant_builder_add (&builder, "{sv}", "parameter-type", g_variant_new_signature (type));
484 g_free (type);
485 }
486
487 if (action->parameter_hint)
488 g_variant_builder_add (&builder, "{sv}", "parameter-hint", action->parameter_hint);
489
490 return g_variant_builder_end (&builder);
491}
492
493/*<internal>
494 * _messaging_menu_message_to_variant:
495 * @msg: a #MessagingMenuMessage
496 *
497 * Serializes @msg to a #GVariant of the form (sssssxaa{sv}b):
498 *
499 * id
500 * icon
501 * title
502 * subtitle
503 * body
504 * time
505 * array of action dictionaries
506 * draws_attention
507 *
508 * Returns: a new floating #GVariant instance
509 */
510GVariant *
511_messaging_menu_message_to_variant (MessagingMenuMessage *msg)
512{
513 GVariantBuilder builder;
514 GSList *it;
515
516 g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
517
518 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sssssxaa{sv}b)"));
519
520 g_variant_builder_add (&builder, "s", msg->id);
521
522 if (msg->icon)
523 {
524 gchar *iconstr;
525
526 iconstr = g_icon_to_string (msg->icon);
527 g_variant_builder_add (&builder, "s", iconstr);
528
529 g_free (iconstr);
530 }
531 else
532 g_variant_builder_add (&builder, "s", "");
533
534 g_variant_builder_add (&builder, "s", msg->title ? msg->title : "");
535 g_variant_builder_add (&builder, "s", msg->subtitle ? msg->subtitle : "");
536 g_variant_builder_add (&builder, "s", msg->body ? msg->body : "");
537 g_variant_builder_add (&builder, "x", msg->time);
538
539 g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{sv}"));
540 for (it = msg->actions; it; it = it->next)
541 g_variant_builder_add_value (&builder, action_to_variant (it->data));
542 g_variant_builder_close (&builder);
543
544 g_variant_builder_add (&builder, "b", msg->draws_attention);
545
546 return g_variant_builder_end (&builder);
547}
0548
=== added file 'libmessaging-menu/messaging-menu-message.h'
--- libmessaging-menu/messaging-menu-message.h 1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu-message.h 2013-07-12 19:50:34 +0000
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#ifndef __messaging_menu_message_h__
21#define __messaging_menu_message_h__
22
23#include <gio/gio.h>
24
25G_BEGIN_DECLS
26
27#define MESSAGING_MENU_TYPE_MESSAGE (messaging_menu_message_get_type ())
28#define MESSAGING_MENU_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessage))
29#define MESSAGING_MENU_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessageClass))
30#define MESSAGING_MENU_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MESSAGING_MENU_TYPE_MESSAGE))
31#define MESSAGING_MENU_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MESSAGING_MENU_TYPE_MESSAGE))
32#define MESSAGING_MENU_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessageClass))
33
34typedef struct _MessagingMenuMessage MessagingMenuMessage;
35
36GType messaging_menu_message_get_type (void) G_GNUC_CONST;
37
38MessagingMenuMessage * messaging_menu_message_new (const gchar *id,
39 GIcon *icon,
40 const gchar *title,
41 const gchar *subtitle,
42 const gchar *body,
43 gint64 time);
44
45const gchar * messaging_menu_message_get_id (MessagingMenuMessage *msg);
46
47GIcon * messaging_menu_message_get_icon (MessagingMenuMessage *msg);
48
49const gchar * messaging_menu_message_get_title (MessagingMenuMessage *msg);
50
51const gchar * messaging_menu_message_get_subtitle (MessagingMenuMessage *msg);
52
53const gchar * messaging_menu_message_get_body (MessagingMenuMessage *msg);
54
55gint64 messaging_menu_message_get_time (MessagingMenuMessage *msg);
56
57gboolean messaging_menu_message_get_draws_attention (MessagingMenuMessage *msg);
58
59void messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
60 gboolean draws_attention);
61
62void messaging_menu_message_add_action (MessagingMenuMessage *msg,
63 const gchar *id,
64 const gchar *label,
65 const GVariantType *parameter_type,
66 GVariant *parameter_hint);
67
68G_END_DECLS
69
70#endif
071
=== added file 'libmessaging-menu/messaging-menu.h'
--- libmessaging-menu/messaging-menu.h 1970-01-01 00:00:00 +0000
+++ libmessaging-menu/messaging-menu.h 2013-07-12 19:50:34 +0000
@@ -0,0 +1,25 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#ifndef __messaging_menu_h__
21#define __messaging_menu_h__
22
23#include "messaging-menu-app.h"
24
25#endif
026
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2012-09-03 13:37:23 +0000
+++ src/Makefile.am 2013-07-12 19:50:34 +0000
@@ -1,8 +1,5 @@
11
2BUILT_SOURCES =
3EXTRA_DIST =2EXTRA_DIST =
4CLEANFILES =
5DISTCLEANFILES =
63
7libexec_PROGRAMS = indicator-messages-service4libexec_PROGRAMS = indicator-messages-service
85
@@ -23,19 +20,20 @@
23 im-source-menu-item.h \20 im-source-menu-item.h \
24 ido-detail-label.c \21 ido-detail-label.c \
25 ido-detail-label.h \22 ido-detail-label.h \
26 indicator-messages-service.c \
27 indicator-messages-service.h
28 dbus-data.h23 dbus-data.h
29libmessaging_la_CFLAGS = \24libmessaging_la_CFLAGS = \
30 $(APPLET_CFLAGS) \25 $(APPLET_CFLAGS) \
31 $(COVERAGE_CFLAGS) \26 $(COVERAGE_CFLAGS) \
27 -I$(top_builddir)/common \
32 -Wall \28 -Wall \
33 -Wl,-Bsymbolic-functions \29 -Wl,-Bsymbolic-functions \
34 -Wl,-z,defs \30 -Wl,-z,defs \
35 -Wl,--as-needed \31 -Wl,--as-needed \
36 -Werror \32 -Werror \
37 -DG_LOG_DOMAIN=\"Indicator-Messages\"33 -DG_LOG_DOMAIN=\"Indicator-Messages\"
38libmessaging_la_LIBADD = $(APPLET_LIBS) -lm34libmessaging_la_LIBADD = \
35 $(top_builddir)/common/libmessaging-common.la \
36 $(APPLET_LIBS) -lm
39libmessaging_la_LDFLAGS = \37libmessaging_la_LDFLAGS = \
40 $(COVERAGE_LDFLAGS) \38 $(COVERAGE_LDFLAGS) \
41 -module -avoid-version39 -module -avoid-version
@@ -46,8 +44,6 @@
4644
47indicator_messages_service_SOURCES = \45indicator_messages_service_SOURCES = \
48 messages-service.c \46 messages-service.c \
49 indicator-messages-service.c \
50 indicator-messages-service.h \
51 app-section.c \47 app-section.c \
52 app-section.h \48 app-section.h \
53 dbus-data.h \49 dbus-data.h \
@@ -56,11 +52,16 @@
56 gsettingsstrv.c \52 gsettingsstrv.c \
57 gsettingsstrv.h \53 gsettingsstrv.h \
58 gmenuutils.c \54 gmenuutils.c \
59 gmenuutils.h55 gmenuutils.h \
56 im-phone-menu.c \
57 im-phone-menu.h \
58 im-application-list.c \
59 im-application-list.h
6060
61indicator_messages_service_CFLAGS = \61indicator_messages_service_CFLAGS = \
62 $(APPLET_CFLAGS) \62 $(APPLET_CFLAGS) \
63 $(COVERAGE_CFLAGS) \63 $(COVERAGE_CFLAGS) \
64 -I$(top_builddir)/common \
64 -Wall \65 -Wall \
65 -Wl,-Bsymbolic-functions \66 -Wl,-Bsymbolic-functions \
66 -Wl,-z,defs \67 -Wl,-z,defs \
@@ -69,26 +70,11 @@
69 -DG_LOG_DOMAIN=\"Indicator-Messages\"70 -DG_LOG_DOMAIN=\"Indicator-Messages\"
7071
71indicator_messages_service_LDADD = \72indicator_messages_service_LDADD = \
73 $(top_builddir)/common/libmessaging-common.la \
72 $(APPLET_LIBS)74 $(APPLET_LIBS)
7375
74indicator_messages_service_LDFLAGS = \76indicator_messages_service_LDFLAGS = \
75 $(COVERAGE_LDFLAGS)77 $(COVERAGE_LDFLAGS)
7678
77indicator-messages-service.c: $(top_srcdir)/src/messages-service.xml
78 $(AM_V_GEN) gdbus-codegen \
79 --interface-prefix com.canonical.indicator.messages. \
80 --generate-c-code indicator-messages-service \
81 --c-namespace IndicatorMessages \
82 $^
83indicator-messages-service.h: indicator-messages-service.c
84
85BUILT_SOURCES += \
86 indicator-messages-service.c \
87 indicator-messages-service.h
88
89EXTRA_DIST += \79EXTRA_DIST += \
90 messages-service.xml80 messages-service.xml
91
92CLEANFILES += \
93 $(BUILT_SOURCES)
94
9581
=== modified file 'src/app-section.c'
--- src/app-section.c 2013-04-22 15:26:51 +0000
+++ src/app-section.c 2013-07-12 19:50:34 +0000
@@ -34,6 +34,7 @@
34#include "dbus-data.h"34#include "dbus-data.h"
35#include "gmenuutils.h"35#include "gmenuutils.h"
36#include "gactionmuxer.h"36#include "gactionmuxer.h"
37#include "indicator-messages-application.h"
3738
38struct _AppSectionPrivate39struct _AppSectionPrivate
39{40{
@@ -42,11 +43,14 @@
4243
43 IndicatorDesktopShortcuts * ids;44 IndicatorDesktopShortcuts * ids;
4445
46 GCancellable *app_proxy_cancellable;
47 IndicatorMessagesApplication *app_proxy;
48
45 GMenu *menu;49 GMenu *menu;
46 GMenuModel *source_menu;50 GMenu *source_menu;
4751
48 GSimpleActionGroup *static_shortcuts;52 GSimpleActionGroup *static_shortcuts;
49 GActionGroup *source_actions;53 GSimpleActionGroup *source_actions;
50 GActionMuxer *muxer;54 GActionMuxer *muxer;
5155
52 gboolean draws_attention;56 gboolean draws_attention;
@@ -90,19 +94,6 @@
90 gpointer user_data);94 gpointer user_data);
91static void app_section_set_app_info (AppSection *self,95static void app_section_set_app_info (AppSection *self,
92 GDesktopAppInfo *appinfo);96 GDesktopAppInfo *appinfo);
93static gboolean any_action_draws_attention (GActionGroup *group,
94 const gchar *ignored_action);
95static void action_added (GActionGroup *group,
96 const gchar *action_name,
97 gpointer user_data);
98static void action_state_changed (GActionGroup *group,
99 const gchar *action_name,
100 GVariant *value,
101 gpointer user_data);
102static void action_removed (GActionGroup *group,
103 const gchar *action_name,
104 gpointer user_data);
105static gboolean action_draws_attention (GVariant *state);
106static void desktop_file_changed_cb (GFileMonitor *monitor,97static void desktop_file_changed_cb (GFileMonitor *monitor,
107 GFile *file,98 GFile *file,
108 GFile *other_file,99 GFile *other_file,
@@ -170,6 +161,7 @@
170app_section_init (AppSection *self)161app_section_init (AppSection *self)
171{162{
172 AppSectionPrivate *priv;163 AppSectionPrivate *priv;
164 GMenuItem *item;
173165
174 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,166 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
175 APP_SECTION_TYPE,167 APP_SECTION_TYPE,
@@ -179,10 +171,19 @@
179 priv->appinfo = NULL;171 priv->appinfo = NULL;
180172
181 priv->menu = g_menu_new ();173 priv->menu = g_menu_new ();
174
175 priv->source_menu = g_menu_new ();
176 item = g_menu_item_new_section (NULL, G_MENU_MODEL (priv->source_menu));
177 g_menu_item_set_attribute (item, "action-namespace", "s", "source");
178 g_menu_append_item (priv->menu, item);
179 g_object_unref (item);
180
182 priv->static_shortcuts = g_simple_action_group_new ();181 priv->static_shortcuts = g_simple_action_group_new ();
182 priv->source_actions = g_simple_action_group_new ();
183183
184 priv->muxer = g_action_muxer_new ();184 priv->muxer = g_action_muxer_new ();
185 g_action_muxer_insert (priv->muxer, NULL, G_ACTION_GROUP (priv->static_shortcuts));185 g_action_muxer_insert (priv->muxer, NULL, G_ACTION_GROUP (priv->static_shortcuts));
186 g_action_muxer_insert (priv->muxer, "source", G_ACTION_GROUP (priv->source_actions));
186187
187 priv->draws_attention = FALSE;188 priv->draws_attention = FALSE;
188189
@@ -249,32 +250,30 @@
249 AppSection * self = APP_SECTION(object);250 AppSection * self = APP_SECTION(object);
250 AppSectionPrivate * priv = self->priv;251 AppSectionPrivate * priv = self->priv;
251252
253 if (priv->app_proxy_cancellable) {
254 g_cancellable_cancel (priv->app_proxy_cancellable);
255 g_clear_object (&priv->app_proxy_cancellable);
256 }
257
252 if (priv->desktop_file_monitor) {258 if (priv->desktop_file_monitor) {
253 g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);259 g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
254 g_clear_object (&priv->desktop_file_monitor);260 g_clear_object (&priv->desktop_file_monitor);
255 }261 }
256262
263 g_clear_object (&priv->app_proxy);
264
257 g_clear_object (&priv->menu);265 g_clear_object (&priv->menu);
266 g_clear_object (&priv->source_menu);
258 g_clear_object (&priv->static_shortcuts);267 g_clear_object (&priv->static_shortcuts);
268 g_clear_object (&priv->source_actions);
259269
260 if (priv->name_watch_id) {270 if (priv->name_watch_id) {
261 g_bus_unwatch_name (priv->name_watch_id);271 g_bus_unwatch_name (priv->name_watch_id);
262 priv->name_watch_id = 0;272 priv->name_watch_id = 0;
263 }273 }
264274
265 if (priv->source_actions) {
266 g_action_muxer_remove (priv->muxer, "source");
267 g_object_disconnect (priv->source_actions,
268 "any_signal::action-added", action_added, self,
269 "any_signal::action-state-changed", action_state_changed, self,
270 "any_signal::action-removed", action_removed, self,
271 NULL);
272 g_clear_object (&priv->source_actions);
273 }
274
275 g_clear_object (&priv->muxer);275 g_clear_object (&priv->muxer);
276276
277 g_clear_object (&priv->source_menu);
278 g_clear_object (&priv->ids);277 g_clear_object (&priv->ids);
279 g_clear_object (&priv->appinfo);278 g_clear_object (&priv->appinfo);
280279
@@ -314,9 +313,13 @@
314313
315 g_return_if_fail(priv->ids != NULL);314 g_return_if_fail(priv->ids != NULL);
316315
316<<<<<<< TREE
317 GAppLaunchContext *context = get_launch_context (g_variant_get_uint32 (param));317 GAppLaunchContext *context = get_launch_context (g_variant_get_uint32 (param));
318318
319 if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, context)) {319 if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, context)) {
320=======
321 if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, NULL)) {
322>>>>>>> MERGE-SOURCE
320 g_warning("Unable to execute nick '%s' for desktop file '%s'",323 g_warning("Unable to execute nick '%s' for desktop file '%s'",
321 nick, g_desktop_app_info_get_filename (priv->appinfo));324 nick, g_desktop_app_info_get_filename (priv->appinfo));
322 }325 }
@@ -445,6 +448,11 @@
445 g_free(name);448 g_free(name);
446 }449 }
447450
451 item = g_menu_item_new_section (NULL, G_MENU_MODEL (priv->source_menu));
452 g_menu_item_set_attribute (item, "action-namespace", "s", "source");
453 g_menu_append_item (priv->menu, item);
454 g_object_unref (item);
455
448 keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));456 keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
449 g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);457 g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
450458
@@ -583,39 +591,8 @@
583void591void
584app_section_clear_draws_attention (AppSection *self)592app_section_clear_draws_attention (AppSection *self)
585{593{
586 AppSectionPrivate * priv = self->priv;594 self->priv->draws_attention = FALSE;
587 gchar **action_names;595 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
588 gchar **it;
589
590 if (priv->source_actions == NULL)
591 return;
592
593 action_names = g_action_group_list_actions (priv->source_actions);
594
595 for (it = action_names; *it; it++) {
596 GVariant *state;
597
598 state = g_action_group_get_action_state (priv->source_actions, *it);
599 if (!state)
600 continue;
601
602 /* clear draws-attention while preserving other state */
603 if (action_draws_attention (state)) {
604 guint32 count;
605 gint64 time;
606 const gchar *str;
607 GVariant *new_state;
608
609 g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL);
610
611 new_state = g_variant_new ("(uxsb)", count, time, str, FALSE);
612 g_action_group_change_action_state (priv->source_actions, *it, new_state);
613 }
614
615 g_variant_unref (state);
616 }
617
618 g_strfreev (action_names);
619}596}
620597
621static void598static void
@@ -628,6 +605,230 @@
628 app_section_unset_object_path (self);605 app_section_unset_object_path (self);
629}606}
630607
608static void
609update_draws_attention (AppSection *self)
610{
611 AppSectionPrivate *priv = self->priv;
612 gchar **actions;
613 gchar **it;
614 gboolean draws_attention = FALSE;
615
616 actions = g_action_group_list_actions (G_ACTION_GROUP (priv->source_actions));
617
618 for (it = actions; *it; it++) {
619 GVariant *state;
620
621 state = g_action_group_get_action_state (G_ACTION_GROUP (priv->source_actions), *it);
622 if (state) {
623 gboolean b;
624 g_variant_get (state, "(uxsb)", NULL, NULL, NULL, &b);
625 draws_attention = b || draws_attention;
626 g_variant_unref (state);
627 }
628
629 if (draws_attention)
630 break;
631 }
632
633 if (draws_attention != priv->draws_attention) {
634 priv->draws_attention = draws_attention;
635 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
636 }
637
638 g_strfreev (actions);
639}
640
641static void
642remove_source (AppSection *self,
643 const gchar *id)
644{
645 AppSectionPrivate *priv = self->priv;
646 guint n_items;
647 guint i;
648
649 n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->source_menu));
650 for (i = 0; i < n_items; i++) {
651 gchar *action;
652 gboolean found = FALSE;
653
654 if (g_menu_model_get_item_attribute (G_MENU_MODEL (priv->source_menu), i,
655 G_MENU_ATTRIBUTE_ACTION, "s", &action)) {
656 found = g_str_equal (action, id);
657 g_free (action);
658 }
659
660 if (found) {
661 g_menu_remove (priv->source_menu, i);
662 break;
663 }
664 }
665
666 g_simple_action_group_remove (priv->source_actions, id);
667 update_draws_attention (self);
668}
669
670static void
671source_action_activated (GSimpleAction *action,
672 GVariant *parameter,
673 gpointer user_data)
674{
675 AppSection *self = APP_SECTION (user_data);
676 AppSectionPrivate *priv = APP_SECTION (user_data)->priv;
677
678 g_return_if_fail (priv->app_proxy != NULL);
679
680 indicator_messages_application_call_activate_source (priv->app_proxy,
681 g_action_get_name (G_ACTION (action)),
682 priv->app_proxy_cancellable,
683 NULL, NULL);
684
685 remove_source (self, g_action_get_name (G_ACTION (action)));
686}
687
688static void
689sources_listed (GObject *source_object,
690 GAsyncResult *result,
691 gpointer user_data)
692{
693 AppSection *self = user_data;
694 AppSectionPrivate *priv = self->priv;
695 GVariant *sources = NULL;
696 GError *error = NULL;
697 GVariantIter iter;
698 const gchar *id;
699 const gchar *label;
700 const gchar *iconstr;
701 guint32 count;
702 gint64 time;
703 const gchar *string;
704 gboolean draws_attention;
705
706 if (!indicator_messages_application_call_list_sources_finish (INDICATOR_MESSAGES_APPLICATION (source_object),
707 &sources, result, &error))
708 {
709 g_warning ("could not fetch the list of sources: %s", error->message);
710 g_error_free (error);
711 return;
712 }
713
714 g_menu_clear (priv->source_menu);
715 g_simple_action_group_clear (priv->source_actions);
716 priv->draws_attention = FALSE;
717
718 g_variant_iter_init (&iter, sources);
719 while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr,
720 &count, &time, &string, &draws_attention))
721 {
722 GVariant *state;
723 GSimpleAction *action;
724 GMenuItem *item;
725
726 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
727 action = g_simple_action_new_stateful (id, NULL, state);
728 g_signal_connect (action, "activate", G_CALLBACK (source_action_activated), self);
729 g_simple_action_group_insert (priv->source_actions, G_ACTION (action));
730
731 item = g_menu_item_new (label, id);
732 g_menu_item_set_attribute (item, "x-canonical-type", "s", "ImSourceMenuItem");
733 g_menu_append_item (priv->source_menu, item);
734
735 priv->draws_attention = priv->draws_attention || draws_attention;
736
737 g_object_unref (item);
738 g_object_unref (action);
739 }
740
741 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
742
743 g_variant_unref (sources);
744}
745
746static void
747source_added (IndicatorMessagesApplication *app,
748 const gchar *id,
749 const gchar *label,
750 const gchar *iconstr,
751 guint count,
752 gint64 time,
753 const gchar *string,
754 gboolean draws_attention,
755 gpointer user_data)
756{
757 AppSection *self = user_data;
758 AppSectionPrivate *priv = self->priv;
759 GVariant *state;
760 GSimpleAction *action;
761
762 /* TODO put label and icon into the action as well */
763
764 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
765 action = g_simple_action_new_stateful (id, NULL, state);
766
767 g_simple_action_group_insert (priv->source_actions, G_ACTION (action));
768
769 if (draws_attention && !priv->draws_attention) {
770 priv->draws_attention = TRUE;
771 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
772 }
773
774 g_object_unref (action);
775}
776static void
777source_changed (IndicatorMessagesApplication *app,
778 const gchar *id,
779 const gchar *label,
780 const gchar *iconstr,
781 guint count,
782 gint64 time,
783 const gchar *string,
784 gboolean draws_attention,
785 gpointer user_data)
786{
787 AppSection *self = user_data;
788 AppSectionPrivate *priv = self->priv;
789 GVariant *state;
790
791 /* TODO put label and icon into the action as well */
792
793 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
794 g_action_group_change_action_state (G_ACTION_GROUP (priv->source_actions), id, state);
795
796 update_draws_attention (self);
797}
798
799static void
800source_removed (IndicatorMessagesApplication *app,
801 const gchar *id,
802 gpointer user_data)
803{
804 AppSection *self = user_data;
805
806 remove_source (self, id);
807}
808
809static void
810app_proxy_created (GObject *source_object,
811 GAsyncResult *result,
812 gpointer user_data)
813{
814 AppSectionPrivate *priv = APP_SECTION (user_data)->priv;
815 GError *error = NULL;
816
817 priv->app_proxy = indicator_messages_application_proxy_new_finish (result, &error);
818 if (!priv->app_proxy) {
819 g_warning ("could not create application proxy: %s", error->message);
820 g_error_free (error);
821 return;
822 }
823
824 indicator_messages_application_call_list_sources (priv->app_proxy, priv->app_proxy_cancellable,
825 sources_listed, user_data);
826
827 g_signal_connect (priv->app_proxy, "source-added", G_CALLBACK (source_added), user_data);
828 g_signal_connect (priv->app_proxy, "source-changed", G_CALLBACK (source_changed), user_data);
829 g_signal_connect (priv->app_proxy, "source-removed", G_CALLBACK (source_removed), user_data);
830}
831
631/*832/*
632 * app_section_set_object_path:833 * app_section_set_object_path:
633 * @self: an #AppSection834 * @self: an #AppSection
@@ -646,27 +847,20 @@
646 const gchar *object_path)847 const gchar *object_path)
647{848{
648 AppSectionPrivate *priv = self->priv;849 AppSectionPrivate *priv = self->priv;
649 GMenuItem *item;
650850
651 g_object_freeze_notify (G_OBJECT (self));851 g_object_freeze_notify (G_OBJECT (self));
652 app_section_unset_object_path (self);852 app_section_unset_object_path (self);
653853
654 priv->source_actions = G_ACTION_GROUP (g_dbus_action_group_get (bus, bus_name, object_path));854 priv->app_proxy_cancellable = g_cancellable_new ();
655 g_action_muxer_insert (priv->muxer, "source", priv->source_actions);855 indicator_messages_application_proxy_new (bus,
656856 G_DBUS_PROXY_FLAGS_NONE,
657 priv->draws_attention = any_action_draws_attention (priv->source_actions, NULL);857 bus_name,
658 g_object_connect (priv->source_actions,858 object_path,
659 "signal::action-added", action_added, self,859 priv->app_proxy_cancellable,
660 "signal::action-state-changed", action_state_changed, self,860 app_proxy_created,
661 "signal::action-removed", action_removed, self,861 self);
662 NULL);862
663863 priv->draws_attention = FALSE;
664 priv->source_menu = G_MENU_MODEL (g_dbus_menu_model_get (bus, bus_name, object_path));
665
666 item = g_menu_item_new_section (NULL, priv->source_menu);
667 g_menu_item_set_attribute (item, "action-namespace", "s", "source");
668 g_menu_append_item (priv->menu, item);
669 g_object_unref (item);
670864
671 priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,865 priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,
672 NULL, application_vanished,866 NULL, application_vanished,
@@ -694,26 +888,19 @@
694{888{
695 AppSectionPrivate *priv = self->priv;889 AppSectionPrivate *priv = self->priv;
696890
891 if (priv->app_proxy_cancellable) {
892 g_cancellable_cancel (priv->app_proxy_cancellable);
893 g_clear_object (&priv->app_proxy_cancellable);
894 }
895 g_clear_object (&priv->app_proxy);
896
697 if (priv->name_watch_id) {897 if (priv->name_watch_id) {
698 g_bus_unwatch_name (priv->name_watch_id);898 g_bus_unwatch_name (priv->name_watch_id);
699 priv->name_watch_id = 0;899 priv->name_watch_id = 0;
700 }900 }
701901
702 if (priv->source_actions) {902 g_simple_action_group_clear (priv->source_actions);
703 g_object_disconnect (priv->source_actions,903 g_menu_clear (priv->source_menu);
704 "any_signal::action-added", action_added, self,
705 "any_signal::action-state-changed", action_state_changed, self,
706 "any_signal::action-removed", action_removed, self,
707 NULL);
708 g_clear_object (&priv->source_actions);
709 }
710
711 if (priv->source_menu) {
712 /* the last menu item points is linked to the app's menumodel */
713 gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu));
714 g_menu_remove (priv->menu, n_items -1);
715 g_clear_object (&priv->source_menu);
716 }
717904
718 priv->draws_attention = FALSE;905 priv->draws_attention = FALSE;
719 g_clear_pointer (&priv->chat_status, g_free);906 g_clear_pointer (&priv->chat_status, g_free);
@@ -727,85 +914,6 @@
727 "launch", g_variant_new_boolean (FALSE));914 "launch", g_variant_new_boolean (FALSE));
728}915}
729916
730static gboolean
731action_draws_attention (GVariant *state)
732{
733 gboolean attention;
734
735 if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")))
736 g_variant_get_child (state, 3, "b", &attention);
737 else
738 attention = FALSE;
739
740 return attention;
741}
742
743static gboolean
744any_action_draws_attention (GActionGroup *group,
745 const gchar *ignored_action)
746{
747 gchar **actions;
748 gchar **it;
749 gboolean attention = FALSE;
750
751 actions = g_action_group_list_actions (group);
752
753 for (it = actions; *it && !attention; it++) {
754 GVariant *state;
755
756 if (ignored_action && g_str_equal (ignored_action, *it))
757 continue;
758
759 state = g_action_group_get_action_state (group, *it);
760 if (state) {
761 attention = action_draws_attention (state);
762 g_variant_unref (state);
763 }
764 }
765
766 g_strfreev (actions);
767 return attention;
768}
769
770static void
771action_added (GActionGroup *group,
772 const gchar *action_name,
773 gpointer user_data)
774{
775 AppSection *self = user_data;
776 GVariant *state;
777
778 state = g_action_group_get_action_state (group, action_name);
779 if (state) {
780 self->priv->draws_attention |= action_draws_attention (state);
781 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
782 g_variant_unref (state);
783 }
784}
785
786static void
787action_state_changed (GActionGroup *group,
788 const gchar *action_name,
789 GVariant *value,
790 gpointer user_data)
791{
792 AppSection *self = user_data;
793
794 self->priv->draws_attention = any_action_draws_attention (group, NULL);
795 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
796}
797
798static void
799action_removed (GActionGroup *group,
800 const gchar *action_name,
801 gpointer user_data)
802{
803 AppSection *self = user_data;
804
805 self->priv->draws_attention = any_action_draws_attention (group, action_name);
806 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
807}
808
809gboolean917gboolean
810app_section_get_uses_chat_status (AppSection *self)918app_section_get_uses_chat_status (AppSection *self)
811{919{
812920
=== modified file 'src/dbus-data.h'
--- src/dbus-data.h 2012-08-21 09:40:47 +0000
+++ src/dbus-data.h 2013-07-12 19:50:34 +0000
@@ -1,9 +1,24 @@
1/*
2 * Copyright 2012-2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
116
2#ifndef __DBUS_DATA_H__17#ifndef __DBUS_DATA_H__
3#define __DBUS_DATA_H__ 118#define __DBUS_DATA_H__ 1
419
5#define INDICATOR_MESSAGES_DBUS_NAME "com.canonical.indicator.messages"20#define INDICATOR_MESSAGES_DBUS_NAME "com.canonical.indicator.messages"
6#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/canonical/indicator/messages/menu"21#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/canonical/indicator/messages"
722
8#define INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT "/com/canonical/indicator/messages/service"23#define INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT "/com/canonical/indicator/messages/service"
9#define INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE "com.canonical.indicator.messages.service"24#define INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE "com.canonical.indicator.messages.service"
1025
=== modified file 'src/gactionmuxer.c'
--- src/gactionmuxer.c 2012-06-04 21:43:56 +0000
+++ src/gactionmuxer.c 2013-07-12 19:50:34 +0000
@@ -483,3 +483,11 @@
483 g_clear_object (&muxer->global_actions);483 g_clear_object (&muxer->global_actions);
484}484}
485485
486GActionGroup *
487g_action_muxer_get_group (GActionMuxer *muxer,
488 const gchar *prefix)
489{
490 g_return_val_if_fail (G_IS_ACTION_MUXER (muxer), NULL);
491
492 return prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions;
493}
486494
=== modified file 'src/gactionmuxer.h'
--- src/gactionmuxer.h 2012-06-03 06:33:31 +0000
+++ src/gactionmuxer.h 2013-07-12 19:50:34 +0000
@@ -40,5 +40,8 @@
40void g_action_muxer_remove (GActionMuxer *muxer,40void g_action_muxer_remove (GActionMuxer *muxer,
41 const gchar *prefix);41 const gchar *prefix);
4242
43GActionGroup * g_action_muxer_get_group (GActionMuxer *muxer,
44 const gchar *prefix);
45
43#endif46#endif
4447
4548
=== modified file 'src/ido-detail-label.c'
--- src/ido-detail-label.c 2013-05-29 13:55:39 +0000
+++ src/ido-detail-label.c 2013-07-12 19:50:34 +0000
@@ -138,6 +138,7 @@
138gtk_widget_get_font_metrics (GtkWidget *widget,138gtk_widget_get_font_metrics (GtkWidget *widget,
139 PangoContext *context)139 PangoContext *context)
140{140{
141<<<<<<< TREE
141 PangoFontDescription *font;142 PangoFontDescription *font;
142 PangoFontMetrics *metrics;143 PangoFontMetrics *metrics;
143144
@@ -151,6 +152,20 @@
151152
152 pango_font_description_free (font);153 pango_font_description_free (font);
153 return metrics;154 return metrics;
155=======
156 PangoFontMetrics *font_metrics;
157 PangoFontDescription *font;
158 GtkStyleContext *style;
159 style = gtk_widget_get_style_context (GTK_WIDGET (widget));
160 gtk_style_context_get (style, GTK_STATE_FLAG_NORMAL,
161 "font", &font, NULL);
162
163 font_metrics = pango_context_get_metrics (context,
164 font,
165 pango_context_get_language (context));
166 pango_font_description_free (font);
167 return font_metrics;
168>>>>>>> MERGE-SOURCE
154}169}
155170
156static gint171static gint
157172
=== added file 'src/im-application-list.c'
--- src/im-application-list.c 1970-01-01 00:00:00 +0000
+++ src/im-application-list.c 2013-07-12 19:50:34 +0000
@@ -0,0 +1,880 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#include "im-application-list.h"
21
22#include "indicator-messages-application.h"
23#include "gactionmuxer.h"
24
25#include <gio/gdesktopappinfo.h>
26#include <string.h>
27
28typedef GObjectClass ImApplicationListClass;
29
30struct _ImApplicationList
31{
32 GObject parent;
33
34 GHashTable *applications;
35 GActionMuxer *muxer;
36};
37
38G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT);
39
40enum
41{
42 SOURCE_ADDED,
43 SOURCE_CHANGED,
44 SOURCE_REMOVED,
45 MESSAGE_ADDED,
46 MESSAGE_REMOVED,
47 APP_STOPPED,
48 REMOVE_ALL,
49 N_SIGNALS
50};
51
52static guint signals[N_SIGNALS];
53
54typedef struct
55{
56 ImApplicationList *list;
57 GDesktopAppInfo *info;
58 gchar *id;
59 IndicatorMessagesApplication *proxy;
60 GActionMuxer *actions;
61 GSimpleActionGroup *source_actions;
62 GSimpleActionGroup *message_actions;
63 GActionMuxer *message_sub_actions;
64 GCancellable *cancellable;
65} Application;
66
67static void
68application_free (gpointer data)
69{
70 Application *app = data;
71
72 if (!app)
73 return;
74
75 g_object_unref (app->info);
76 g_free (app->id);
77
78 if (app->cancellable)
79 {
80 g_cancellable_cancel (app->cancellable);
81 g_clear_object (&app->cancellable);
82 }
83
84 if (app->proxy)
85 g_object_unref (app->proxy);
86
87 if (app->actions)
88 {
89 g_object_unref (app->actions);
90 g_object_unref (app->source_actions);
91 g_object_unref (app->message_actions);
92 g_object_unref (app->message_sub_actions);
93 }
94
95 g_slice_free (Application, app);
96}
97
98static void
99im_application_list_source_removed (Application *app,
100 const gchar *id)
101{
102 g_simple_action_group_remove (app->source_actions, id);
103
104 g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id);
105}
106
107static void
108im_application_list_source_activated (GSimpleAction *action,
109 GVariant *parameter,
110 gpointer user_data)
111{
112 Application *app = user_data;
113 const gchar *source_id;
114
115 source_id = g_action_get_name (G_ACTION (action));
116
117 if (g_variant_get_boolean (parameter))
118 {
119 indicator_messages_application_call_activate_source (app->proxy,
120 source_id,
121 app->cancellable,
122 NULL, NULL);
123 }
124 else
125 {
126 const gchar *sources[] = { source_id, NULL };
127 const gchar *messages[] = { NULL };
128 indicator_messages_application_call_dismiss (app->proxy, sources, messages,
129 app->cancellable, NULL, NULL);
130 }
131
132 im_application_list_source_removed (app, source_id);
133}
134
135static guint
136g_action_group_get_n_actions (GActionGroup *group)
137{
138 guint len;
139 gchar **actions;
140
141 actions = g_action_group_list_actions (group);
142 len = g_strv_length (actions);
143
144 g_strfreev (actions);
145 return len;
146}
147
148static gboolean
149application_draws_attention (gpointer key,
150 gpointer value,
151 gpointer user_data)
152{
153 Application *app = value;
154
155 return (g_action_group_get_n_actions (G_ACTION_GROUP (app->source_actions)) +
156 g_action_group_get_n_actions (G_ACTION_GROUP (app->message_actions))) > 0;
157}
158
159static void
160im_application_list_update_draws_attention (ImApplicationList *list)
161{
162 const gchar *icon_name;
163 GVariant *state;
164 GActionGroup *main_actions;
165
166 if (g_hash_table_find (list->applications, application_draws_attention, NULL))
167 icon_name = "indicator-messages-new";
168 else
169 icon_name = "indicator-messages";
170
171 main_actions = g_action_muxer_get_group (list->muxer, NULL);
172 state = g_variant_new ("(sssb)", "", icon_name, "Messages", TRUE);
173 g_action_group_change_action_state (main_actions, "messages", state);
174}
175
176static void
177im_application_list_message_removed (Application *app,
178 const gchar *id)
179{
180 g_simple_action_group_remove (app->message_actions, id);
181 g_action_muxer_remove (app->message_sub_actions, id);
182
183 im_application_list_update_draws_attention (app->list);
184
185 g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id);
186}
187
188static void
189im_application_list_message_activated (GSimpleAction *action,
190 GVariant *parameter,
191 gpointer user_data)
192{
193 Application *app = user_data;
194 const gchar *message_id;
195
196 message_id = g_action_get_name (G_ACTION (action));
197
198 if (g_variant_get_boolean (parameter))
199 {
200 indicator_messages_application_call_activate_message (app->proxy,
201 message_id,
202 "",
203 g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0),
204 app->cancellable,
205 NULL, NULL);
206 }
207 else
208 {
209 const gchar *sources[] = { NULL };
210 const gchar *messages[] = { message_id, NULL };
211 indicator_messages_application_call_dismiss (app->proxy, sources, messages,
212 app->cancellable, NULL, NULL);
213 }
214
215 im_application_list_message_removed (app, message_id);
216}
217
218static void
219im_application_list_sub_message_activated (GSimpleAction *action,
220 GVariant *parameter,
221 gpointer user_data)
222{
223 Application *app = user_data;
224 const gchar *message_id;
225 const gchar *action_id;
226 GVariantBuilder builder;
227
228 message_id = g_object_get_data (G_OBJECT (action), "message");
229 action_id = g_action_get_name (G_ACTION (action));
230
231 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
232 if (parameter)
233 g_variant_builder_add (&builder, "v", parameter);
234
235 indicator_messages_application_call_activate_message (app->proxy,
236 message_id,
237 action_id,
238 g_variant_builder_end (&builder),
239 app->cancellable,
240 NULL, NULL);
241
242 im_application_list_message_removed (app, message_id);
243}
244
245
246static void
247im_application_list_remove_all (GSimpleAction *action,
248 GVariant *parameter,
249 gpointer user_data)
250{
251 ImApplicationList *list = user_data;
252 GHashTableIter iter;
253 Application *app;
254
255 g_signal_emit (list, signals[REMOVE_ALL], 0);
256
257 g_hash_table_iter_init (&iter, list->applications);
258 while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app))
259 {
260 gchar **source_actions;
261 gchar **message_actions;
262 gchar **it;
263
264 source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions));
265 for (it = source_actions; *it; it++)
266 im_application_list_source_removed (app, *it);
267
268 message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions));
269 for (it = message_actions; *it; it++)
270 im_application_list_message_removed (app, *it);
271
272 indicator_messages_application_call_dismiss (app->proxy,
273 (const gchar * const *) source_actions,
274 (const gchar * const *) message_actions,
275 app->cancellable, NULL, NULL);
276
277 g_strfreev (source_actions);
278 g_strfreev (message_actions);
279 }
280}
281
282static void
283im_application_list_dispose (GObject *object)
284{
285 ImApplicationList *list = IM_APPLICATION_LIST (object);
286
287 g_clear_pointer (&list->applications, g_hash_table_unref);
288 g_clear_object (&list->muxer);
289
290 G_OBJECT_CLASS (im_application_list_parent_class)->dispose (object);
291}
292
293static void
294im_application_list_finalize (GObject *object)
295{
296 G_OBJECT_CLASS (im_application_list_parent_class)->finalize (object);
297}
298
299static void
300im_application_list_class_init (ImApplicationListClass *klass)
301{
302 GObjectClass *object_class = G_OBJECT_CLASS (klass);
303
304 object_class->dispose = im_application_list_dispose;
305 object_class->finalize = im_application_list_finalize;
306
307 signals[SOURCE_ADDED] = g_signal_new ("source-added",
308 IM_TYPE_APPLICATION_LIST,
309 G_SIGNAL_RUN_FIRST,
310 0,
311 NULL, NULL,
312 g_cclosure_marshal_generic,
313 G_TYPE_NONE,
314 4,
315 G_TYPE_STRING,
316 G_TYPE_STRING,
317 G_TYPE_STRING,
318 G_TYPE_STRING);
319
320 signals[SOURCE_CHANGED] = g_signal_new ("source-changed",
321 IM_TYPE_APPLICATION_LIST,
322 G_SIGNAL_RUN_FIRST,
323 0,
324 NULL, NULL,
325 g_cclosure_marshal_generic,
326 G_TYPE_NONE,
327 4,
328 G_TYPE_STRING,
329 G_TYPE_STRING,
330 G_TYPE_STRING,
331 G_TYPE_STRING);
332
333 signals[SOURCE_REMOVED] = g_signal_new ("source-removed",
334 IM_TYPE_APPLICATION_LIST,
335 G_SIGNAL_RUN_FIRST,
336 0,
337 NULL, NULL,
338 g_cclosure_marshal_generic,
339 G_TYPE_NONE,
340 2,
341 G_TYPE_STRING,
342 G_TYPE_STRING);
343
344 signals[MESSAGE_ADDED] = g_signal_new ("message-added",
345 IM_TYPE_APPLICATION_LIST,
346 G_SIGNAL_RUN_FIRST,
347 0,
348 NULL, NULL,
349 g_cclosure_marshal_generic,
350 G_TYPE_NONE,
351 10,
352 G_TYPE_STRING,
353 G_TYPE_STRING,
354 G_TYPE_STRING,
355 G_TYPE_STRING,
356 G_TYPE_STRING,
357 G_TYPE_STRING,
358 G_TYPE_STRING,
359 G_TYPE_VARIANT,
360 G_TYPE_INT64,
361 G_TYPE_BOOLEAN);
362
363 signals[MESSAGE_REMOVED] = g_signal_new ("message-removed",
364 IM_TYPE_APPLICATION_LIST,
365 G_SIGNAL_RUN_FIRST,
366 0,
367 NULL, NULL,
368 g_cclosure_marshal_generic,
369 G_TYPE_NONE,
370 2,
371 G_TYPE_STRING,
372 G_TYPE_STRING);
373
374 signals[APP_STOPPED] = g_signal_new ("app-stopped",
375 IM_TYPE_APPLICATION_LIST,
376 G_SIGNAL_RUN_FIRST,
377 0,
378 NULL, NULL,
379 g_cclosure_marshal_VOID__OBJECT,
380 G_TYPE_NONE,
381 1,
382 G_TYPE_STRING);
383
384 signals[REMOVE_ALL] = g_signal_new ("remove-all",
385 IM_TYPE_APPLICATION_LIST,
386 G_SIGNAL_RUN_FIRST,
387 0,
388 NULL, NULL,
389 g_cclosure_marshal_VOID__VOID,
390 G_TYPE_NONE,
391 0);
392}
393
394static void
395im_application_list_init (ImApplicationList *list)
396{
397 const GActionEntry action_entries[] = {
398 { "messages", NULL, NULL, "('', 'indicator-messages', 'Messages', true)", NULL },
399 { "remove-all", im_application_list_remove_all }
400 };
401
402 GSimpleActionGroup *actions;
403
404 list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free);
405
406 actions = g_simple_action_group_new ();
407 g_simple_action_group_add_entries (actions, action_entries, G_N_ELEMENTS (action_entries), list);
408
409 list->muxer = g_action_muxer_new ();
410 g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (actions));
411
412 g_object_unref (actions);
413}
414
415ImApplicationList *
416im_application_list_new (void)
417{
418 return g_object_new (IM_TYPE_APPLICATION_LIST, NULL);
419}
420
421static gchar *
422im_application_list_canonical_id (const gchar *id)
423{
424 gchar *str;
425 gchar *p;
426 int len;
427
428 len = strlen (id);
429 if (g_str_has_suffix (id, ".desktop"))
430 len -= 8;
431
432 str = g_strndup (id, len);
433
434 for (p = str; *p; p++)
435 {
436 if (*p == '.')
437 *p = '_';
438 }
439
440 return str;
441}
442
443static Application *
444im_application_list_lookup (ImApplicationList *list,
445 const gchar *desktop_id)
446{
447 gchar *id;
448 Application *app;
449
450 id = im_application_list_canonical_id (desktop_id);
451 app = g_hash_table_lookup (list->applications, id);
452
453 g_free (id);
454 return app;
455}
456
457void
458im_application_list_add (ImApplicationList *list,
459 const gchar *desktop_id)
460{
461 GDesktopAppInfo *info;
462 Application *app;
463 const gchar *id;
464
465 g_return_if_fail (IM_IS_APPLICATION_LIST (list));
466 g_return_if_fail (desktop_id != NULL);
467
468 if (im_application_list_lookup (list, desktop_id))
469 return;
470
471 info = g_desktop_app_info_new (desktop_id);
472 if (!info)
473 {
474 g_warning ("an application with id '%s' is not installed", desktop_id);
475 return;
476 }
477
478 id = g_app_info_get_id (G_APP_INFO (info));
479 g_return_if_fail (id != NULL);
480
481 app = g_slice_new0 (Application);
482 app->info = info;
483 app->id = im_application_list_canonical_id (id);
484 app->list = list;
485 app->actions = g_action_muxer_new ();
486 app->source_actions = g_simple_action_group_new ();
487 app->message_actions = g_simple_action_group_new ();
488 app->message_sub_actions = g_action_muxer_new ();
489
490 g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
491 g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
492 g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
493
494 g_hash_table_insert (list->applications, (gpointer) app->id, app);
495 g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions));
496}
497
498void
499im_application_list_remove (ImApplicationList *list,
500 const gchar *id)
501{
502 Application *app;
503
504 g_return_if_fail (IM_IS_APPLICATION_LIST (list));
505
506 app = im_application_list_lookup (list, id);
507 if (app)
508 {
509 if (app->proxy || app->cancellable)
510 g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id);
511
512 g_hash_table_remove (list->applications, id);
513 g_action_muxer_remove (list->muxer, id);
514 }
515}
516
517static void
518im_application_list_source_added (Application *app,
519 guint position,
520 GVariant *source)
521{
522 const gchar *id;
523 const gchar *label;
524 const gchar *iconstr;
525 guint32 count;
526 gint64 time;
527 const gchar *string;
528 gboolean draws_attention;
529 GVariant *state;
530 GSimpleAction *action;
531
532 g_variant_get (source, "(&s&s&sux&sb)",
533 &id, &label, &iconstr, &count, &time, &string, &draws_attention);
534
535 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
536 action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state);
537 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app);
538
539 g_simple_action_group_insert (app->source_actions, G_ACTION (action));
540
541 g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr);
542
543 g_object_unref (action);
544}
545
546static void
547im_application_list_source_changed (Application *app,
548 GVariant *source)
549{
550 const gchar *id;
551 const gchar *label;
552 const gchar *iconstr;
553 guint32 count;
554 gint64 time;
555 const gchar *string;
556 gboolean draws_attention;
557
558 g_variant_get (source, "(&s&s&sux&sb)",
559 &id, &label, &iconstr, &count, &time, &string, &draws_attention);
560
561 g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id,
562 g_variant_new ("(uxsb)", count, time, string, draws_attention));
563
564 g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr);
565}
566
567static void
568im_application_list_sources_listed (GObject *source_object,
569 GAsyncResult *result,
570 gpointer user_data)
571{
572 Application *app = user_data;
573 GVariant *sources;
574 GError *error = NULL;
575
576 if (indicator_messages_application_call_list_sources_finish (app->proxy, &sources, result, &error))
577 {
578 GVariantIter iter;
579 GVariant *source;
580 guint i = 0;
581
582 g_variant_iter_init (&iter, sources);
583 while ((source = g_variant_iter_next_value (&iter)))
584 {
585 im_application_list_source_added (app, i++, source);
586 g_variant_unref (source);
587 }
588
589 g_variant_unref (sources);
590 }
591 else
592 {
593 g_warning ("could not fetch the list of sources: %s", error->message);
594 g_error_free (error);
595 }
596}
597
598static gchar *
599get_symbolic_app_icon_string (GIcon *icon)
600{
601 const gchar * const *names;
602 gchar *symbolic_name;
603 GIcon *symbolic_icon;
604 gchar *str;
605
606 if (!G_IS_THEMED_ICON (icon))
607 return NULL;
608
609 names = g_themed_icon_get_names (G_THEMED_ICON (icon));
610 if (!names || !names[0])
611 return NULL;
612
613 symbolic_icon = g_themed_icon_new_from_names ((gchar **) names, -1);
614
615 symbolic_name = g_strconcat (names[0], "-symbolic", NULL);
616 g_themed_icon_prepend_name (G_THEMED_ICON (symbolic_icon), symbolic_name);
617
618 str = g_icon_to_string (symbolic_icon);
619
620 g_free (symbolic_name);
621 g_object_unref (symbolic_icon);
622 return str;
623}
624
625static void
626im_application_list_message_added (Application *app,
627 GVariant *message)
628{
629 const gchar *id;
630 const gchar *iconstr;
631 const gchar *title;
632 const gchar *subtitle;
633 const gchar *body;
634 gint64 time;
635 GVariantIter *action_iter;
636 gboolean draws_attention;
637 GSimpleAction *action;
638 GIcon *app_icon;
639 gchar *app_iconstr = NULL;
640 GVariant *actions = NULL;
641
642 g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)",
643 &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
644
645 app_icon = g_app_info_get_icon (G_APP_INFO (app->info));
646 if (app_icon)
647 app_iconstr = get_symbolic_app_icon_string (app_icon);
648
649 action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN);
650 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);
651 g_simple_action_group_insert (app->message_actions, G_ACTION (action));
652
653 {
654 GVariant *entry;
655 GSimpleActionGroup *action_group;
656 GVariantBuilder actions_builder;
657
658 g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
659 action_group = g_simple_action_group_new ();
660
661 while ((entry = g_variant_iter_next_value (action_iter)))
662 {
663 const gchar *name;
664 GSimpleAction *action;
665 GVariant *label;
666 const gchar *type = NULL;
667 GVariant *hint;
668 GVariantBuilder dict_builder;
669 gchar *prefixed_name;
670
671 if (!g_variant_lookup (entry, "name", "&s", &name))
672 {
673 g_warning ("action dictionary for message '%s' is missing 'name' key", id);
674 continue;
675 }
676
677 label = g_variant_lookup_value (entry, "label", G_VARIANT_TYPE_STRING);
678 g_variant_lookup (entry, "parameter-type", "&g", &type);
679 hint = g_variant_lookup_value (entry, "parameter-hint", NULL);
680
681 action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL);
682 g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);
683 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);
684 g_simple_action_group_insert (action_group, G_ACTION (action));
685
686 g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));
687
688 prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL);
689 g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));
690
691 if (label)
692 {
693 g_variant_builder_add (&dict_builder, "{sv}", "label", label);
694 g_variant_unref (label);
695 }
696
697 if (type)
698 g_variant_builder_add (&dict_builder, "{sv}", "parameter-type", g_variant_new_string (type));
699
700 if (hint)
701 {
702 g_variant_builder_add (&dict_builder, "{sv}", "parameter-hint", hint);
703 g_variant_unref (hint);
704 }
705
706 g_variant_builder_add (&actions_builder, "a{sv}", &dict_builder);
707
708 g_object_unref (action);
709 g_variant_unref (entry);
710 g_free (prefixed_name);
711 }
712
713 g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group));
714 actions = g_variant_builder_end (&actions_builder);
715
716 g_object_unref (action_group);
717 }
718
719 im_application_list_update_draws_attention (app->list);
720
721 g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
722 app->id, app_iconstr, id, iconstr, title,
723 subtitle, body, actions, time, draws_attention);
724
725 g_variant_iter_free (action_iter);
726 g_free (app_iconstr);
727 g_object_unref (action);
728}
729
730static void
731im_application_list_messages_listed (GObject *source_object,
732 GAsyncResult *result,
733 gpointer user_data)
734{
735 Application *app = user_data;
736 GVariant *messages;
737 GError *error = NULL;
738
739 if (indicator_messages_application_call_list_messages_finish (app->proxy, &messages, result, &error))
740 {
741 GVariantIter iter;
742 GVariant *message;
743
744 g_variant_iter_init (&iter, messages);
745 while ((message = g_variant_iter_next_value (&iter)))
746 {
747 im_application_list_message_added (app, message);
748 g_variant_unref (message);
749 }
750
751 g_variant_unref (messages);
752 }
753 else
754 {
755 g_warning ("could not fetch the list of messages: %s", error->message);
756 g_error_free (error);
757 }
758}
759
760static void
761im_application_list_unset_remote (Application *app)
762{
763 gboolean was_running;
764
765 was_running = app->proxy || app->cancellable;
766
767 if (app->cancellable)
768 {
769 g_cancellable_cancel (app->cancellable);
770 g_clear_object (&app->cancellable);
771 }
772 g_clear_object (&app->proxy);
773
774 /* clear actions by creating a new action group and overriding it in
775 * the muxer */
776 g_object_unref (app->source_actions);
777 g_object_unref (app->message_actions);
778 g_object_unref (app->message_sub_actions);
779 app->source_actions = g_simple_action_group_new ();
780 app->message_actions = g_simple_action_group_new ();
781 app->message_sub_actions = g_action_muxer_new ();
782 g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
783 g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
784 g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
785
786 im_application_list_update_draws_attention (app->list);
787
788 if (was_running)
789 g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id);
790}
791
792static void
793im_application_list_app_vanished (GDBusConnection *connection,
794 const gchar *name,
795 gpointer user_data)
796{
797 Application *app = user_data;
798
799 im_application_list_unset_remote (app);
800}
801
802static void
803im_application_list_proxy_created (GObject *source_object,
804 GAsyncResult *result,
805 gpointer user_data)
806{
807 Application *app = user_data;
808 GError *error = NULL;
809
810 app->proxy = indicator_messages_application_proxy_new_finish (result, &error);
811 if (!app->proxy)
812 {
813 if (error->code != G_IO_ERROR_CANCELLED)
814 g_warning ("could not create application proxy: %s", error->message);
815 g_error_free (error);
816 return;
817 }
818
819 indicator_messages_application_call_list_sources (app->proxy, app->cancellable,
820 im_application_list_sources_listed, app);
821 indicator_messages_application_call_list_messages (app->proxy, app->cancellable,
822 im_application_list_messages_listed, app);
823
824 g_signal_connect_swapped (app->proxy, "source-added", G_CALLBACK (im_application_list_source_added), app);
825 g_signal_connect_swapped (app->proxy, "source-changed", G_CALLBACK (im_application_list_source_changed), app);
826 g_signal_connect_swapped (app->proxy, "source-removed", G_CALLBACK (im_application_list_source_removed), app);
827 g_signal_connect_swapped (app->proxy, "message-added", G_CALLBACK (im_application_list_message_added), app);
828 g_signal_connect_swapped (app->proxy, "message-removed", G_CALLBACK (im_application_list_message_removed), app);
829
830 g_bus_watch_name_on_connection (g_dbus_proxy_get_connection (G_DBUS_PROXY (app->proxy)),
831 g_dbus_proxy_get_name (G_DBUS_PROXY (app->proxy)),
832 G_BUS_NAME_WATCHER_FLAGS_NONE,
833 NULL, im_application_list_app_vanished,
834 app, NULL);
835}
836
837void
838im_application_list_set_remote (ImApplicationList *list,
839 const gchar *id,
840 GDBusConnection *connection,
841 const gchar *unique_bus_name,
842 const gchar *object_path)
843{
844 Application *app;
845
846 g_return_if_fail (IM_IS_APPLICATION_LIST (list));
847
848 app = im_application_list_lookup (list, id);
849 if (!app)
850 {
851 g_warning ("'%s' is not a registered application", id);
852 return;
853 }
854
855 if (app->cancellable)
856 {
857 gchar *name_owner = NULL;
858
859 if (app->proxy)
860 name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy));
861 g_warning ("replacing '%s' at %s with %s", id, name_owner, unique_bus_name);
862
863 im_application_list_unset_remote (app);
864
865 g_free (name_owner);
866 }
867
868 app->cancellable = g_cancellable_new ();
869 indicator_messages_application_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
870 unique_bus_name, object_path, app->cancellable,
871 im_application_list_proxy_created, app);
872}
873
874GActionGroup *
875im_application_list_get_action_group (ImApplicationList *list)
876{
877 g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), NULL);
878
879 return G_ACTION_GROUP (list->muxer);
880}
0881
=== added file 'src/im-application-list.h'
--- src/im-application-list.h 1970-01-01 00:00:00 +0000
+++ src/im-application-list.h 2013-07-12 19:50:34 +0000
@@ -0,0 +1,52 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#ifndef __IM_APPLICATION_LIST_H__
21#define __IM_APPLICATION_LIST_H__
22
23#include <gio/gio.h>
24
25#define IM_TYPE_APPLICATION_LIST (im_application_list_get_type ())
26#define IM_APPLICATION_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_TYPE_APPLICATION_LIST, ImApplicationList))
27#define IM_APPLICATION_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IM_TYPE_APPLICATION_LIST, ImApplicationListClass))
28#define IM_IS_APPLICATION_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_TYPE_APPLICATION_LIST))
29#define IM_IS_APPLICATION_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_TYPE_APPLICATION_LIST))
30#define IM_APPLICATION_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_TYPE_APPLICATION_LIST, ImApplicationListClass))
31
32typedef struct _ImApplicationList ImApplicationList;
33
34GType im_application_list_get_type (void);
35
36ImApplicationList * im_application_list_new (void);
37
38void im_application_list_add (ImApplicationList *list,
39 const gchar *desktop_id);
40
41void im_application_list_remove (ImApplicationList *list,
42 const gchar *id);
43
44void im_application_list_set_remote (ImApplicationList *list,
45 const gchar *id,
46 GDBusConnection *connection,
47 const gchar *unique_bus_name,
48 const gchar *object_path);
49
50GActionGroup * im_application_list_get_action_group (ImApplicationList *list);
51
52#endif
053
=== added file 'src/im-phone-menu.c'
--- src/im-phone-menu.c 1970-01-01 00:00:00 +0000
+++ src/im-phone-menu.c 2013-07-12 19:50:34 +0000
@@ -0,0 +1,331 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Lars Uebernickel <lars.uebernickel@canonical.com>
18 */
19
20#include "im-phone-menu.h"
21
22#include <string.h>
23
24typedef GObjectClass ImPhoneMenuClass;
25
26struct _ImPhoneMenu
27{
28 GObject parent;
29
30 GMenu *toplevel_menu;
31 GMenu *message_section;
32 GMenu *source_section;
33
34};
35
36G_DEFINE_TYPE (ImPhoneMenu, im_phone_menu, G_TYPE_OBJECT);
37
38typedef void (*ImMenuForeachFunc) (GMenuModel *menu, gint pos);
39
40static void
41im_phone_menu_foreach_item_with_action (GMenuModel *menu,
42 const gchar *action,
43 ImMenuForeachFunc func)
44{
45 gint n_items;
46 gint i;
47
48 n_items = g_menu_model_get_n_items (menu);
49 for (i = 0; i < n_items; i++)
50 {
51 gchar *item_action;
52
53 g_menu_model_get_item_attribute (menu, i, G_MENU_ATTRIBUTE_ACTION, "s", &item_action);
54
55 if (g_str_equal (action, item_action))
56 func (menu, i);
57
58 g_free (item_action);
59 }
60}
61
62static void
63im_phone_menu_update_toplevel (ImPhoneMenu *menu)
64{
65 if (g_menu_model_get_n_items (G_MENU_MODEL (menu->message_section)) ||
66 g_menu_model_get_n_items (G_MENU_MODEL (menu->source_section)))
67 {
68 if (g_menu_model_get_n_items (G_MENU_MODEL (menu->toplevel_menu)) == 0)
69 {
70 GMenuItem *item;
71
72 g_menu_append_section (menu->toplevel_menu, NULL, G_MENU_MODEL (menu->message_section));
73 g_menu_append_section (menu->toplevel_menu, NULL, G_MENU_MODEL (menu->source_section));
74
75 item = g_menu_item_new ("Clear All", "remove-all");
76 g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.button");
77 g_menu_append_item (menu->toplevel_menu, item);
78
79 g_object_unref (item);
80 }
81 }
82 else
83 {
84 while (g_menu_model_get_n_items (G_MENU_MODEL (menu->toplevel_menu)))
85 g_menu_remove (menu->toplevel_menu, 0);
86 }
87}
88
89static void
90im_phone_menu_dispose (GObject *object)
91{
92 ImPhoneMenu *menu = IM_PHONE_MENU (object);
93
94 g_clear_object (&menu->toplevel_menu);
95 g_clear_object (&menu->message_section);
96 g_clear_object (&menu->source_section);
97
98 G_OBJECT_CLASS (im_phone_menu_parent_class)->dispose (object);
99}
100
101static void
102im_phone_menu_finalize (GObject *object)
103{
104 G_OBJECT_CLASS (im_phone_menu_parent_class)->finalize (object);
105}
106
107static void
108im_phone_menu_class_init (ImPhoneMenuClass *klass)
109{
110 GObjectClass *object_class = G_OBJECT_CLASS (klass);
111
112 object_class->dispose = im_phone_menu_dispose;
113 object_class->finalize = im_phone_menu_finalize;
114}
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: