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
1=== added file 'COPYING.GPLv3'
2--- COPYING.GPLv3 1970-01-01 00:00:00 +0000
3+++ COPYING.GPLv3 2013-07-12 19:50:34 +0000
4@@ -0,0 +1,674 @@
5+ GNU GENERAL PUBLIC LICENSE
6+ Version 3, 29 June 2007
7+
8+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
9+ Everyone is permitted to copy and distribute verbatim copies
10+ of this license document, but changing it is not allowed.
11+
12+ Preamble
13+
14+ The GNU General Public License is a free, copyleft license for
15+software and other kinds of works.
16+
17+ The licenses for most software and other practical works are designed
18+to take away your freedom to share and change the works. By contrast,
19+the GNU General Public License is intended to guarantee your freedom to
20+share and change all versions of a program--to make sure it remains free
21+software for all its users. We, the Free Software Foundation, use the
22+GNU General Public License for most of our software; it applies also to
23+any other work released this way by its authors. You can apply it to
24+your programs, too.
25+
26+ When we speak of free software, we are referring to freedom, not
27+price. Our General Public Licenses are designed to make sure that you
28+have the freedom to distribute copies of free software (and charge for
29+them if you wish), that you receive source code or can get it if you
30+want it, that you can change the software or use pieces of it in new
31+free programs, and that you know you can do these things.
32+
33+ To protect your rights, we need to prevent others from denying you
34+these rights or asking you to surrender the rights. Therefore, you have
35+certain responsibilities if you distribute copies of the software, or if
36+you modify it: responsibilities to respect the freedom of others.
37+
38+ For example, if you distribute copies of such a program, whether
39+gratis or for a fee, you must pass on to the recipients the same
40+freedoms that you received. You must make sure that they, too, receive
41+or can get the source code. And you must show them these terms so they
42+know their rights.
43+
44+ Developers that use the GNU GPL protect your rights with two steps:
45+(1) assert copyright on the software, and (2) offer you this License
46+giving you legal permission to copy, distribute and/or modify it.
47+
48+ For the developers' and authors' protection, the GPL clearly explains
49+that there is no warranty for this free software. For both users' and
50+authors' sake, the GPL requires that modified versions be marked as
51+changed, so that their problems will not be attributed erroneously to
52+authors of previous versions.
53+
54+ Some devices are designed to deny users access to install or run
55+modified versions of the software inside them, although the manufacturer
56+can do so. This is fundamentally incompatible with the aim of
57+protecting users' freedom to change the software. The systematic
58+pattern of such abuse occurs in the area of products for individuals to
59+use, which is precisely where it is most unacceptable. Therefore, we
60+have designed this version of the GPL to prohibit the practice for those
61+products. If such problems arise substantially in other domains, we
62+stand ready to extend this provision to those domains in future versions
63+of the GPL, as needed to protect the freedom of users.
64+
65+ Finally, every program is threatened constantly by software patents.
66+States should not allow patents to restrict development and use of
67+software on general-purpose computers, but in those that do, we wish to
68+avoid the special danger that patents applied to a free program could
69+make it effectively proprietary. To prevent this, the GPL assures that
70+patents cannot be used to render the program non-free.
71+
72+ The precise terms and conditions for copying, distribution and
73+modification follow.
74+
75+ TERMS AND CONDITIONS
76+
77+ 0. Definitions.
78+
79+ "This License" refers to version 3 of the GNU General Public License.
80+
81+ "Copyright" also means copyright-like laws that apply to other kinds of
82+works, such as semiconductor masks.
83+
84+ "The Program" refers to any copyrightable work licensed under this
85+License. Each licensee is addressed as "you". "Licensees" and
86+"recipients" may be individuals or organizations.
87+
88+ To "modify" a work means to copy from or adapt all or part of the work
89+in a fashion requiring copyright permission, other than the making of an
90+exact copy. The resulting work is called a "modified version" of the
91+earlier work or a work "based on" the earlier work.
92+
93+ A "covered work" means either the unmodified Program or a work based
94+on the Program.
95+
96+ To "propagate" a work means to do anything with it that, without
97+permission, would make you directly or secondarily liable for
98+infringement under applicable copyright law, except executing it on a
99+computer or modifying a private copy. Propagation includes copying,
100+distribution (with or without modification), making available to the
101+public, and in some countries other activities as well.
102+
103+ To "convey" a work means any kind of propagation that enables other
104+parties to make or receive copies. Mere interaction with a user through
105+a computer network, with no transfer of a copy, is not conveying.
106+
107+ An interactive user interface displays "Appropriate Legal Notices"
108+to the extent that it includes a convenient and prominently visible
109+feature that (1) displays an appropriate copyright notice, and (2)
110+tells the user that there is no warranty for the work (except to the
111+extent that warranties are provided), that licensees may convey the
112+work under this License, and how to view a copy of this License. If
113+the interface presents a list of user commands or options, such as a
114+menu, a prominent item in the list meets this criterion.
115+
116+ 1. Source Code.
117+
118+ The "source code" for a work means the preferred form of the work
119+for making modifications to it. "Object code" means any non-source
120+form of a work.
121+
122+ A "Standard Interface" means an interface that either is an official
123+standard defined by a recognized standards body, or, in the case of
124+interfaces specified for a particular programming language, one that
125+is widely used among developers working in that language.
126+
127+ The "System Libraries" of an executable work include anything, other
128+than the work as a whole, that (a) is included in the normal form of
129+packaging a Major Component, but which is not part of that Major
130+Component, and (b) serves only to enable use of the work with that
131+Major Component, or to implement a Standard Interface for which an
132+implementation is available to the public in source code form. A
133+"Major Component", in this context, means a major essential component
134+(kernel, window system, and so on) of the specific operating system
135+(if any) on which the executable work runs, or a compiler used to
136+produce the work, or an object code interpreter used to run it.
137+
138+ The "Corresponding Source" for a work in object code form means all
139+the source code needed to generate, install, and (for an executable
140+work) run the object code and to modify the work, including scripts to
141+control those activities. However, it does not include the work's
142+System Libraries, or general-purpose tools or generally available free
143+programs which are used unmodified in performing those activities but
144+which are not part of the work. For example, Corresponding Source
145+includes interface definition files associated with source files for
146+the work, and the source code for shared libraries and dynamically
147+linked subprograms that the work is specifically designed to require,
148+such as by intimate data communication or control flow between those
149+subprograms and other parts of the work.
150+
151+ The Corresponding Source need not include anything that users
152+can regenerate automatically from other parts of the Corresponding
153+Source.
154+
155+ The Corresponding Source for a work in source code form is that
156+same work.
157+
158+ 2. Basic Permissions.
159+
160+ All rights granted under this License are granted for the term of
161+copyright on the Program, and are irrevocable provided the stated
162+conditions are met. This License explicitly affirms your unlimited
163+permission to run the unmodified Program. The output from running a
164+covered work is covered by this License only if the output, given its
165+content, constitutes a covered work. This License acknowledges your
166+rights of fair use or other equivalent, as provided by copyright law.
167+
168+ You may make, run and propagate covered works that you do not
169+convey, without conditions so long as your license otherwise remains
170+in force. You may convey covered works to others for the sole purpose
171+of having them make modifications exclusively for you, or provide you
172+with facilities for running those works, provided that you comply with
173+the terms of this License in conveying all material for which you do
174+not control copyright. Those thus making or running the covered works
175+for you must do so exclusively on your behalf, under your direction
176+and control, on terms that prohibit them from making any copies of
177+your copyrighted material outside their relationship with you.
178+
179+ Conveying under any other circumstances is permitted solely under
180+the conditions stated below. Sublicensing is not allowed; section 10
181+makes it unnecessary.
182+
183+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
184+
185+ No covered work shall be deemed part of an effective technological
186+measure under any applicable law fulfilling obligations under article
187+11 of the WIPO copyright treaty adopted on 20 December 1996, or
188+similar laws prohibiting or restricting circumvention of such
189+measures.
190+
191+ When you convey a covered work, you waive any legal power to forbid
192+circumvention of technological measures to the extent such circumvention
193+is effected by exercising rights under this License with respect to
194+the covered work, and you disclaim any intention to limit operation or
195+modification of the work as a means of enforcing, against the work's
196+users, your or third parties' legal rights to forbid circumvention of
197+technological measures.
198+
199+ 4. Conveying Verbatim Copies.
200+
201+ You may convey verbatim copies of the Program's source code as you
202+receive it, in any medium, provided that you conspicuously and
203+appropriately publish on each copy an appropriate copyright notice;
204+keep intact all notices stating that this License and any
205+non-permissive terms added in accord with section 7 apply to the code;
206+keep intact all notices of the absence of any warranty; and give all
207+recipients a copy of this License along with the Program.
208+
209+ You may charge any price or no price for each copy that you convey,
210+and you may offer support or warranty protection for a fee.
211+
212+ 5. Conveying Modified Source Versions.
213+
214+ You may convey a work based on the Program, or the modifications to
215+produce it from the Program, in the form of source code under the
216+terms of section 4, provided that you also meet all of these conditions:
217+
218+ a) The work must carry prominent notices stating that you modified
219+ it, and giving a relevant date.
220+
221+ b) The work must carry prominent notices stating that it is
222+ released under this License and any conditions added under section
223+ 7. This requirement modifies the requirement in section 4 to
224+ "keep intact all notices".
225+
226+ c) You must license the entire work, as a whole, under this
227+ License to anyone who comes into possession of a copy. This
228+ License will therefore apply, along with any applicable section 7
229+ additional terms, to the whole of the work, and all its parts,
230+ regardless of how they are packaged. This License gives no
231+ permission to license the work in any other way, but it does not
232+ invalidate such permission if you have separately received it.
233+
234+ d) If the work has interactive user interfaces, each must display
235+ Appropriate Legal Notices; however, if the Program has interactive
236+ interfaces that do not display Appropriate Legal Notices, your
237+ work need not make them do so.
238+
239+ A compilation of a covered work with other separate and independent
240+works, which are not by their nature extensions of the covered work,
241+and which are not combined with it such as to form a larger program,
242+in or on a volume of a storage or distribution medium, is called an
243+"aggregate" if the compilation and its resulting copyright are not
244+used to limit the access or legal rights of the compilation's users
245+beyond what the individual works permit. Inclusion of a covered work
246+in an aggregate does not cause this License to apply to the other
247+parts of the aggregate.
248+
249+ 6. Conveying Non-Source Forms.
250+
251+ You may convey a covered work in object code form under the terms
252+of sections 4 and 5, provided that you also convey the
253+machine-readable Corresponding Source under the terms of this License,
254+in one of these ways:
255+
256+ a) Convey the object code in, or embodied in, a physical product
257+ (including a physical distribution medium), accompanied by the
258+ Corresponding Source fixed on a durable physical medium
259+ customarily used for software interchange.
260+
261+ b) Convey the object code in, or embodied in, a physical product
262+ (including a physical distribution medium), accompanied by a
263+ written offer, valid for at least three years and valid for as
264+ long as you offer spare parts or customer support for that product
265+ model, to give anyone who possesses the object code either (1) a
266+ copy of the Corresponding Source for all the software in the
267+ product that is covered by this License, on a durable physical
268+ medium customarily used for software interchange, for a price no
269+ more than your reasonable cost of physically performing this
270+ conveying of source, or (2) access to copy the
271+ Corresponding Source from a network server at no charge.
272+
273+ c) Convey individual copies of the object code with a copy of the
274+ written offer to provide the Corresponding Source. This
275+ alternative is allowed only occasionally and noncommercially, and
276+ only if you received the object code with such an offer, in accord
277+ with subsection 6b.
278+
279+ d) Convey the object code by offering access from a designated
280+ place (gratis or for a charge), and offer equivalent access to the
281+ Corresponding Source in the same way through the same place at no
282+ further charge. You need not require recipients to copy the
283+ Corresponding Source along with the object code. If the place to
284+ copy the object code is a network server, the Corresponding Source
285+ may be on a different server (operated by you or a third party)
286+ that supports equivalent copying facilities, provided you maintain
287+ clear directions next to the object code saying where to find the
288+ Corresponding Source. Regardless of what server hosts the
289+ Corresponding Source, you remain obligated to ensure that it is
290+ available for as long as needed to satisfy these requirements.
291+
292+ e) Convey the object code using peer-to-peer transmission, provided
293+ you inform other peers where the object code and Corresponding
294+ Source of the work are being offered to the general public at no
295+ charge under subsection 6d.
296+
297+ A separable portion of the object code, whose source code is excluded
298+from the Corresponding Source as a System Library, need not be
299+included in conveying the object code work.
300+
301+ A "User Product" is either (1) a "consumer product", which means any
302+tangible personal property which is normally used for personal, family,
303+or household purposes, or (2) anything designed or sold for incorporation
304+into a dwelling. In determining whether a product is a consumer product,
305+doubtful cases shall be resolved in favor of coverage. For a particular
306+product received by a particular user, "normally used" refers to a
307+typical or common use of that class of product, regardless of the status
308+of the particular user or of the way in which the particular user
309+actually uses, or expects or is expected to use, the product. A product
310+is a consumer product regardless of whether the product has substantial
311+commercial, industrial or non-consumer uses, unless such uses represent
312+the only significant mode of use of the product.
313+
314+ "Installation Information" for a User Product means any methods,
315+procedures, authorization keys, or other information required to install
316+and execute modified versions of a covered work in that User Product from
317+a modified version of its Corresponding Source. The information must
318+suffice to ensure that the continued functioning of the modified object
319+code is in no case prevented or interfered with solely because
320+modification has been made.
321+
322+ If you convey an object code work under this section in, or with, or
323+specifically for use in, a User Product, and the conveying occurs as
324+part of a transaction in which the right of possession and use of the
325+User Product is transferred to the recipient in perpetuity or for a
326+fixed term (regardless of how the transaction is characterized), the
327+Corresponding Source conveyed under this section must be accompanied
328+by the Installation Information. But this requirement does not apply
329+if neither you nor any third party retains the ability to install
330+modified object code on the User Product (for example, the work has
331+been installed in ROM).
332+
333+ The requirement to provide Installation Information does not include a
334+requirement to continue to provide support service, warranty, or updates
335+for a work that has been modified or installed by the recipient, or for
336+the User Product in which it has been modified or installed. Access to a
337+network may be denied when the modification itself materially and
338+adversely affects the operation of the network or violates the rules and
339+protocols for communication across the network.
340+
341+ Corresponding Source conveyed, and Installation Information provided,
342+in accord with this section must be in a format that is publicly
343+documented (and with an implementation available to the public in
344+source code form), and must require no special password or key for
345+unpacking, reading or copying.
346+
347+ 7. Additional Terms.
348+
349+ "Additional permissions" are terms that supplement the terms of this
350+License by making exceptions from one or more of its conditions.
351+Additional permissions that are applicable to the entire Program shall
352+be treated as though they were included in this License, to the extent
353+that they are valid under applicable law. If additional permissions
354+apply only to part of the Program, that part may be used separately
355+under those permissions, but the entire Program remains governed by
356+this License without regard to the additional permissions.
357+
358+ When you convey a copy of a covered work, you may at your option
359+remove any additional permissions from that copy, or from any part of
360+it. (Additional permissions may be written to require their own
361+removal in certain cases when you modify the work.) You may place
362+additional permissions on material, added by you to a covered work,
363+for which you have or can give appropriate copyright permission.
364+
365+ Notwithstanding any other provision of this License, for material you
366+add to a covered work, you may (if authorized by the copyright holders of
367+that material) supplement the terms of this License with terms:
368+
369+ a) Disclaiming warranty or limiting liability differently from the
370+ terms of sections 15 and 16 of this License; or
371+
372+ b) Requiring preservation of specified reasonable legal notices or
373+ author attributions in that material or in the Appropriate Legal
374+ Notices displayed by works containing it; or
375+
376+ c) Prohibiting misrepresentation of the origin of that material, or
377+ requiring that modified versions of such material be marked in
378+ reasonable ways as different from the original version; or
379+
380+ d) Limiting the use for publicity purposes of names of licensors or
381+ authors of the material; or
382+
383+ e) Declining to grant rights under trademark law for use of some
384+ trade names, trademarks, or service marks; or
385+
386+ f) Requiring indemnification of licensors and authors of that
387+ material by anyone who conveys the material (or modified versions of
388+ it) with contractual assumptions of liability to the recipient, for
389+ any liability that these contractual assumptions directly impose on
390+ those licensors and authors.
391+
392+ All other non-permissive additional terms are considered "further
393+restrictions" within the meaning of section 10. If the Program as you
394+received it, or any part of it, contains a notice stating that it is
395+governed by this License along with a term that is a further
396+restriction, you may remove that term. If a license document contains
397+a further restriction but permits relicensing or conveying under this
398+License, you may add to a covered work material governed by the terms
399+of that license document, provided that the further restriction does
400+not survive such relicensing or conveying.
401+
402+ If you add terms to a covered work in accord with this section, you
403+must place, in the relevant source files, a statement of the
404+additional terms that apply to those files, or a notice indicating
405+where to find the applicable terms.
406+
407+ Additional terms, permissive or non-permissive, may be stated in the
408+form of a separately written license, or stated as exceptions;
409+the above requirements apply either way.
410+
411+ 8. Termination.
412+
413+ You may not propagate or modify a covered work except as expressly
414+provided under this License. Any attempt otherwise to propagate or
415+modify it is void, and will automatically terminate your rights under
416+this License (including any patent licenses granted under the third
417+paragraph of section 11).
418+
419+ However, if you cease all violation of this License, then your
420+license from a particular copyright holder is reinstated (a)
421+provisionally, unless and until the copyright holder explicitly and
422+finally terminates your license, and (b) permanently, if the copyright
423+holder fails to notify you of the violation by some reasonable means
424+prior to 60 days after the cessation.
425+
426+ Moreover, your license from a particular copyright holder is
427+reinstated permanently if the copyright holder notifies you of the
428+violation by some reasonable means, this is the first time you have
429+received notice of violation of this License (for any work) from that
430+copyright holder, and you cure the violation prior to 30 days after
431+your receipt of the notice.
432+
433+ Termination of your rights under this section does not terminate the
434+licenses of parties who have received copies or rights from you under
435+this License. If your rights have been terminated and not permanently
436+reinstated, you do not qualify to receive new licenses for the same
437+material under section 10.
438+
439+ 9. Acceptance Not Required for Having Copies.
440+
441+ You are not required to accept this License in order to receive or
442+run a copy of the Program. Ancillary propagation of a covered work
443+occurring solely as a consequence of using peer-to-peer transmission
444+to receive a copy likewise does not require acceptance. However,
445+nothing other than this License grants you permission to propagate or
446+modify any covered work. These actions infringe copyright if you do
447+not accept this License. Therefore, by modifying or propagating a
448+covered work, you indicate your acceptance of this License to do so.
449+
450+ 10. Automatic Licensing of Downstream Recipients.
451+
452+ Each time you convey a covered work, the recipient automatically
453+receives a license from the original licensors, to run, modify and
454+propagate that work, subject to this License. You are not responsible
455+for enforcing compliance by third parties with this License.
456+
457+ An "entity transaction" is a transaction transferring control of an
458+organization, or substantially all assets of one, or subdividing an
459+organization, or merging organizations. If propagation of a covered
460+work results from an entity transaction, each party to that
461+transaction who receives a copy of the work also receives whatever
462+licenses to the work the party's predecessor in interest had or could
463+give under the previous paragraph, plus a right to possession of the
464+Corresponding Source of the work from the predecessor in interest, if
465+the predecessor has it or can get it with reasonable efforts.
466+
467+ You may not impose any further restrictions on the exercise of the
468+rights granted or affirmed under this License. For example, you may
469+not impose a license fee, royalty, or other charge for exercise of
470+rights granted under this License, and you may not initiate litigation
471+(including a cross-claim or counterclaim in a lawsuit) alleging that
472+any patent claim is infringed by making, using, selling, offering for
473+sale, or importing the Program or any portion of it.
474+
475+ 11. Patents.
476+
477+ A "contributor" is a copyright holder who authorizes use under this
478+License of the Program or a work on which the Program is based. The
479+work thus licensed is called the contributor's "contributor version".
480+
481+ A contributor's "essential patent claims" are all patent claims
482+owned or controlled by the contributor, whether already acquired or
483+hereafter acquired, that would be infringed by some manner, permitted
484+by this License, of making, using, or selling its contributor version,
485+but do not include claims that would be infringed only as a
486+consequence of further modification of the contributor version. For
487+purposes of this definition, "control" includes the right to grant
488+patent sublicenses in a manner consistent with the requirements of
489+this License.
490+
491+ Each contributor grants you a non-exclusive, worldwide, royalty-free
492+patent license under the contributor's essential patent claims, to
493+make, use, sell, offer for sale, import and otherwise run, modify and
494+propagate the contents of its contributor version.
495+
496+ In the following three paragraphs, a "patent license" is any express
497+agreement or commitment, however denominated, not to enforce a patent
498+(such as an express permission to practice a patent or covenant not to
499+sue for patent infringement). To "grant" such a patent license to a
500+party means to make such an agreement or commitment not to enforce a
501+patent against the party.
502+
503+ If you convey a covered work, knowingly relying on a patent license,
504+and the Corresponding Source of the work is not available for anyone
505+to copy, free of charge and under the terms of this License, through a
506+publicly available network server or other readily accessible means,
507+then you must either (1) cause the Corresponding Source to be so
508+available, or (2) arrange to deprive yourself of the benefit of the
509+patent license for this particular work, or (3) arrange, in a manner
510+consistent with the requirements of this License, to extend the patent
511+license to downstream recipients. "Knowingly relying" means you have
512+actual knowledge that, but for the patent license, your conveying the
513+covered work in a country, or your recipient's use of the covered work
514+in a country, would infringe one or more identifiable patents in that
515+country that you have reason to believe are valid.
516+
517+ If, pursuant to or in connection with a single transaction or
518+arrangement, you convey, or propagate by procuring conveyance of, a
519+covered work, and grant a patent license to some of the parties
520+receiving the covered work authorizing them to use, propagate, modify
521+or convey a specific copy of the covered work, then the patent license
522+you grant is automatically extended to all recipients of the covered
523+work and works based on it.
524+
525+ A patent license is "discriminatory" if it does not include within
526+the scope of its coverage, prohibits the exercise of, or is
527+conditioned on the non-exercise of one or more of the rights that are
528+specifically granted under this License. You may not convey a covered
529+work if you are a party to an arrangement with a third party that is
530+in the business of distributing software, under which you make payment
531+to the third party based on the extent of your activity of conveying
532+the work, and under which the third party grants, to any of the
533+parties who would receive the covered work from you, a discriminatory
534+patent license (a) in connection with copies of the covered work
535+conveyed by you (or copies made from those copies), or (b) primarily
536+for and in connection with specific products or compilations that
537+contain the covered work, unless you entered into that arrangement,
538+or that patent license was granted, prior to 28 March 2007.
539+
540+ Nothing in this License shall be construed as excluding or limiting
541+any implied license or other defenses to infringement that may
542+otherwise be available to you under applicable patent law.
543+
544+ 12. No Surrender of Others' Freedom.
545+
546+ If conditions are imposed on you (whether by court order, agreement or
547+otherwise) that contradict the conditions of this License, they do not
548+excuse you from the conditions of this License. If you cannot convey a
549+covered work so as to satisfy simultaneously your obligations under this
550+License and any other pertinent obligations, then as a consequence you may
551+not convey it at all. For example, if you agree to terms that obligate you
552+to collect a royalty for further conveying from those to whom you convey
553+the Program, the only way you could satisfy both those terms and this
554+License would be to refrain entirely from conveying the Program.
555+
556+ 13. Use with the GNU Affero General Public License.
557+
558+ Notwithstanding any other provision of this License, you have
559+permission to link or combine any covered work with a work licensed
560+under version 3 of the GNU Affero General Public License into a single
561+combined work, and to convey the resulting work. The terms of this
562+License will continue to apply to the part which is the covered work,
563+but the special requirements of the GNU Affero General Public License,
564+section 13, concerning interaction through a network will apply to the
565+combination as such.
566+
567+ 14. Revised Versions of this License.
568+
569+ The Free Software Foundation may publish revised and/or new versions of
570+the GNU General Public License from time to time. Such new versions will
571+be similar in spirit to the present version, but may differ in detail to
572+address new problems or concerns.
573+
574+ Each version is given a distinguishing version number. If the
575+Program specifies that a certain numbered version of the GNU General
576+Public License "or any later version" applies to it, you have the
577+option of following the terms and conditions either of that numbered
578+version or of any later version published by the Free Software
579+Foundation. If the Program does not specify a version number of the
580+GNU General Public License, you may choose any version ever published
581+by the Free Software Foundation.
582+
583+ If the Program specifies that a proxy can decide which future
584+versions of the GNU General Public License can be used, that proxy's
585+public statement of acceptance of a version permanently authorizes you
586+to choose that version for the Program.
587+
588+ Later license versions may give you additional or different
589+permissions. However, no additional obligations are imposed on any
590+author or copyright holder as a result of your choosing to follow a
591+later version.
592+
593+ 15. Disclaimer of Warranty.
594+
595+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
596+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
597+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
598+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
599+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
600+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
601+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
602+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
603+
604+ 16. Limitation of Liability.
605+
606+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
607+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
608+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
609+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
610+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
611+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
612+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
613+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
614+SUCH DAMAGES.
615+
616+ 17. Interpretation of Sections 15 and 16.
617+
618+ If the disclaimer of warranty and limitation of liability provided
619+above cannot be given local legal effect according to their terms,
620+reviewing courts shall apply local law that most closely approximates
621+an absolute waiver of all civil liability in connection with the
622+Program, unless a warranty or assumption of liability accompanies a
623+copy of the Program in return for a fee.
624+
625+ END OF TERMS AND CONDITIONS
626+
627+ How to Apply These Terms to Your New Programs
628+
629+ If you develop a new program, and you want it to be of the greatest
630+possible use to the public, the best way to achieve this is to make it
631+free software which everyone can redistribute and change under these terms.
632+
633+ To do so, attach the following notices to the program. It is safest
634+to attach them to the start of each source file to most effectively
635+state the exclusion of warranty; and each file should have at least
636+the "copyright" line and a pointer to where the full notice is found.
637+
638+ <one line to give the program's name and a brief idea of what it does.>
639+ Copyright (C) <year> <name of author>
640+
641+ This program is free software: you can redistribute it and/or modify
642+ it under the terms of the GNU General Public License as published by
643+ the Free Software Foundation, either version 3 of the License, or
644+ (at your option) any later version.
645+
646+ This program is distributed in the hope that it will be useful,
647+ but WITHOUT ANY WARRANTY; without even the implied warranty of
648+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
649+ GNU General Public License for more details.
650+
651+ You should have received a copy of the GNU General Public License
652+ along with this program. If not, see <http://www.gnu.org/licenses/>.
653+
654+Also add information on how to contact you by electronic and paper mail.
655+
656+ If the program does terminal interaction, make it output a short
657+notice like this when it starts in an interactive mode:
658+
659+ <program> Copyright (C) <year> <name of author>
660+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
661+ This is free software, and you are welcome to redistribute it
662+ under certain conditions; type `show c' for details.
663+
664+The hypothetical commands `show w' and `show c' should show the appropriate
665+parts of the General Public License. Of course, your program's commands
666+might be different; for a GUI interface, you would use an "about box".
667+
668+ You should also get your employer (if you work as a programmer) or school,
669+if any, to sign a "copyright disclaimer" for the program, if necessary.
670+For more information on this, and how to apply and follow the GNU GPL, see
671+<http://www.gnu.org/licenses/>.
672+
673+ The GNU General Public License does not permit incorporating your program
674+into proprietary programs. If your program is a subroutine library, you
675+may consider it more useful to permit linking proprietary applications with
676+the library. If this is what you want to do, use the GNU Lesser General
677+Public License instead of this License. But first, please read
678+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
679
680=== modified file 'Makefile.am'
681--- Makefile.am 2012-08-29 11:27:54 +0000
682+++ Makefile.am 2013-07-12 19:50:34 +0000
683@@ -1,5 +1,6 @@
684
685 SUBDIRS = \
686+ common \
687 src \
688 libmessaging-menu \
689 data \
690
691=== modified file 'autogen.sh'
692--- autogen.sh 2012-08-29 11:27:54 +0000
693+++ autogen.sh 2013-07-12 19:50:34 +0000
694@@ -1,5 +1,11 @@
695-#!/bin/sh -e
696-
697-gtkdocize
698-autoreconf -i -f
699-intltoolize
700+#!/bin/sh
701+
702+PKG_NAME="indicator-messages"
703+
704+which gnome-autogen.sh || {
705+ echo "You need gnome-common from GNOME SVN"
706+ exit 1
707+}
708+
709+USE_GNOME2_MACROS=1 \
710+. gnome-autogen.sh
711
712=== added directory 'common'
713=== added file 'common/Makefile.am'
714--- common/Makefile.am 1970-01-01 00:00:00 +0000
715+++ common/Makefile.am 2013-07-12 19:50:34 +0000
716@@ -0,0 +1,32 @@
717+
718+noinst_LTLIBRARIES = libmessaging-common.la
719+
720+indicator-messages-service.c: com.canonical.indicator.messages.service.xml
721+ $(AM_V_GEN) gdbus-codegen \
722+ --interface-prefix com.canonical.indicator.messages. \
723+ --generate-c-code indicator-messages-service \
724+ --c-namespace IndicatorMessages \
725+ $^
726+indicator-messages-service.h: indicator-messages-service.c
727+
728+indicator-messages-application.c: com.canonical.indicator.messages.application.xml
729+ $(AM_V_GEN) gdbus-codegen \
730+ --interface-prefix com.canonical.indicator.messages. \
731+ --generate-c-code indicator-messages-application \
732+ --c-namespace IndicatorMessages \
733+ $^
734+indicator-messages-application.h: indicator-messages-application.c
735+
736+BUILT_SOURCES = \
737+ indicator-messages-service.c \
738+ indicator-messages-service.h \
739+ indicator-messages-application.c \
740+ indicator-messages-application.h
741+
742+libmessaging_common_la_SOURCES = \
743+ $(BUILT_SOURCES)
744+
745+libmessaging_common_la_CFLAGS = $(GIO_CFLAGS)
746+libmessaging_common_la_LIBADD = $(GIO_LIBS)
747+
748+CLEANFILES = $(BUILT_SOURCES)
749
750=== added file 'common/com.canonical.indicator.messages.application.xml'
751--- common/com.canonical.indicator.messages.application.xml 1970-01-01 00:00:00 +0000
752+++ common/com.canonical.indicator.messages.application.xml 2013-07-12 19:50:34 +0000
753@@ -0,0 +1,39 @@
754+<?xml version="1.0" encoding="UTF-8"?>
755+<node name="/">
756+ <interface name="com.canonical.indicator.messages.application">
757+ <method name="ListSources">
758+ <arg type="a(sssuxsb)" name="sources" direction="out" />
759+ </method>
760+ <method name="ListMessages">
761+ <arg type="a(sssssxaa{sv}b)" name="message" direction="out" />
762+ </method>
763+ <method name="ActivateSource">
764+ <arg type="s" name="source_id" direction="in" />
765+ </method>
766+ <method name="ActivateMessage">
767+ <arg type="s" name="message_id" direction="in" />
768+ <arg type="s" name="action_id" direction="in" />
769+ <arg type="av" name="parameter" direction="in" />
770+ </method>
771+ <method name="Dismiss">
772+ <arg type="as" name="sources" direction="in" />
773+ <arg type="as" name="messages" direction="in" />
774+ </method>
775+ <signal name="SourceAdded">
776+ <arg type="u" name="position" direction="in" />
777+ <arg type="(sssuxsb)" name="source" direction="in" />
778+ </signal>
779+ <signal name="SourceChanged">
780+ <arg type="(sssuxsb)" name="source" direction="in" />
781+ </signal>
782+ <signal name="SourceRemoved">
783+ <arg type="s" name="source_id" direction="in" />
784+ </signal>
785+ <signal name="MessageAdded">
786+ <arg type="(sssssxaa{sv}b)" name="message" direction="in" />
787+ </signal>
788+ <signal name="MessageRemoved">
789+ <arg type="s" name="message_id" direction="in" />
790+ </signal>
791+ </interface>
792+</node>
793
794=== renamed file 'src/messages-service.xml' => 'common/com.canonical.indicator.messages.service.xml'
795=== modified file 'configure.ac'
796--- configure.ac 2013-02-26 00:34:56 +0000
797+++ configure.ac 2013-07-12 19:50:34 +0000
798@@ -128,6 +128,22 @@
799 fi
800 AC_SUBST(DBUSSERVICEDIR)
801
802+###########################
803+# Vala API Generation
804+###########################
805+
806+AC_ARG_ENABLE([vala],
807+ AC_HELP_STRING([--disable-vala], [Disable vala]),
808+ [enable_vala=$enableval], [enable_vala=yes])
809+
810+AS_IF([test "x$enable_vala" != "xno"],[
811+ AM_COND_IF([HAVE_INTROSPECTION],,[
812+ AC_MSG_ERROR([Vala bindings require introspection support, please --enable-introspection])
813+ ])
814+AC_PATH_PROG([VALA_API_GEN], [vapigen])
815+])
816+AM_CONDITIONAL([HAVE_VALA], [test -n "$VALA_API_GEN"])
817+
818 ##############################
819 # Custom Junk
820 ##############################
821@@ -162,6 +178,7 @@
822 AC_OUTPUT([
823 Makefile
824 src/Makefile
825+common/Makefile
826 data/Makefile
827 data/icons/Makefile
828 data/icons/16x16/Makefile
829@@ -202,5 +219,6 @@
830 tests: $enable_tests
831 gcov: $use_gcov
832 introspecion: $enable_introspection
833+ Vala bindings: $enable_vala
834 documentation: $enable_gtk_doc
835 ])
836
837=== modified file 'debian/changelog'
838--- debian/changelog 2013-07-02 02:02:36 +0000
839+++ debian/changelog 2013-07-12 19:50:34 +0000
840@@ -1,3 +1,4 @@
841+<<<<<<< TREE
842 indicator-messages (12.10.6+13.10.20130702-0ubuntu1) saucy; urgency=low
843
844 [ Mathias Dietrich ]
845@@ -104,6 +105,88 @@
846 indicator-messages (12.10.6daily12.11.21.1-0ubuntu1) raring; urgency=low
847
848 [ Mathieu Trudel-Lapierre ]
849+=======
850+indicator-messages (13.10.0phablet1) raring; urgency=low
851+
852+ * Version bump to not pull from archives
853+
854+ -- Sergio Schvezov <sergio.schvezov@canonical.com> Fri, 26 Apr 2013 13:53:53 -0300
855+
856+indicator-messages (12.10.6phablet1) quantal; urgency=low
857+
858+ * Adding guards for g_type_init
859+
860+ -- Sergio Schvezov <sergio.schvezov@canonical.com> Fri, 22 Mar 2013 17:23:45 -0300
861+
862+indicator-messages (12.10.6-0ubuntu1phablet9) quantal; urgency=low
863+
864+ * add "remove-all" signal to imapplicationlist (temporarily)
865+
866+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 20 Dec 2012 18:49:50 +0100
867+
868+indicator-messages (12.10.6-0ubuntu1phablet8) quantal; urgency=low
869+
870+ * Make messaging_menu_app_remove_message() work for messages with a ref count of 1
871+ * Make handling of multiple processes with the same desktop id more robust
872+ * ImPhoneMenu: sort messages by time (fixes LP #1090266)
873+ * Don't show message sources
874+
875+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 17 Dec 2012 14:42:03 +0100
876+
877+indicator-messages (12.10.6-0ubuntu1phablet7) quantal; urgency=low
878+
879+ * Remove variant wrapper from 'parameter' argument of the "activate" signal
880+
881+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Tue, 11 Dec 2012 14:28:15 +0100
882+
883+indicator-messages (12.10.6-0ubuntu1phablet6) quantal; urgency=low
884+
885+ * Don't show sources
886+ * Always use the "messageitem" widget type for messages
887+
888+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 10 Dec 2012 14:38:16 +0100
889+
890+indicator-messages (12.10.6-0ubuntu1phablet5) quantal; urgency=low
891+
892+ * Don't shorten the app id to seven characters (fixes LP #1086729)
893+ * Add messaging_menu_app_get_message
894+
895+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 06 Dec 2012 15:06:34 +0000
896+
897+indicator-messages (12.10.6-0ubuntu1phablet4) quantal; urgency=low
898+
899+ [Lars Uebernickel]
900+ * Add the concept of actions to messages
901+ * Stop using IndicatorService
902+ * Reverse order of messages
903+ * Expose symbolic application icon
904+ * Change icon when there are any messages in the menu
905+
906+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Tue, 04 Dec 2012 21:10:26 +0000
907+
908+indicator-messages (12.10.6-0ubuntu1phablet3) quantal; urgency=low
909+
910+ [Lars Uebernickel]
911+ * expose root menu item of which the indicator menu is a submenu
912+ * fix crash in im-application-list on arm
913+
914+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Thu, 29 Nov 2012 21:44:19 +0100
915+
916+indicator-messages (12.10.6-0ubuntu1phablet2) quantal; urgency=low
917+
918+ [Lars Uebernickel]
919+ * refactor messages-service.c
920+ * notify applications about message and source activations
921+ * add "Clear All" menu item
922+ * allow dismissing of messages
923+ * include application icons on message items
924+
925+ -- Lars Uebernickel <lars.uebernickel@ubuntu.com> Mon, 26 Nov 2012 22:19:51 +0100
926+
927+indicator-messages (12.10.6-0ubuntu1phablet1) quantal; urgency=low
928+
929+ [ Mathieu Trudel-Lapierre ]
930+>>>>>>> MERGE-SOURCE
931 * debian/rules:
932 - Use autogen.sh for dh_autoreconf.
933 - Drop the override for dh_makeshlibs.
934@@ -116,10 +199,17 @@
935 - Clear the detail (count or time) of a source when another type of detail
936 is set. (LP: #1071640)
937
938+<<<<<<< TREE
939 [ Automatic PS uploader ]
940 * Automatic snapshot from revision 331
941
942 -- Automatic PS uploader <ps-jenkins@lists.canonical.com> Wed, 21 Nov 2012 10:41:37 +0000
943+=======
944+ [ Ricardo Mendoza ]
945+ * Releasing upstream for phablet
946+
947+ -- Ricardo Mendoza <ricardo.mendoza@canonical.com> Tue, 20 Nov 2012 10:08:59 -0430
948+>>>>>>> MERGE-SOURCE
949
950 indicator-messages (12.10.5-0ubuntu2) raring; urgency=low
951
952
953=== modified file 'debian/control'
954--- debian/control 2013-06-07 22:15:28 +0000
955+++ debian/control 2013-07-12 19:50:34 +0000
956@@ -7,19 +7,27 @@
957 Build-Depends: debhelper (>= 9),
958 dh-autoreconf,
959 dh-translations,
960+<<<<<<< TREE
961 libglib2.0-dev (>= 2.35.4),
962 libgtk-3-dev (>= 3.5.12),
963+=======
964+ gobject-introspection (>= 0.9.12-4~),
965+ gtk-doc-tools,
966+ intltool,
967+>>>>>>> MERGE-SOURCE
968 libdbus-glib-1-dev,
969- intltool,
970- libindicator3-dev,
971 libdbusmenu-glib-dev (>= 0.5.90),
972 libdbusmenu-gtk3-dev (>= 0.5.90),
973- libtelepathy-glib-dev (>= 0.9.0),
974- gobject-introspection (>= 0.9.12-4~),
975 libgirepository1.0-dev (>= 0.9.12),
976- gtk-doc-tools,
977 libgtest-dev,
978+<<<<<<< TREE
979 python3-dbusmock,
980+=======
981+ libgtk-3-dev (>= 3.5.18),
982+ libindicator3-dev,
983+ libtelepathy-glib-dev (>= 0.9.0),
984+ valac,
985+>>>>>>> MERGE-SOURCE
986 Standards-Version: 3.9.3
987 Homepage: https://launchpad.net/indicator-messages
988 # If you aren't a member of ~indicator-applet-developers but need to upload
989
990=== modified file 'debian/libmessaging-menu-dev.install'
991--- debian/libmessaging-menu-dev.install 2012-09-01 10:35:36 +0000
992+++ debian/libmessaging-menu-dev.install 2013-07-12 19:50:34 +0000
993@@ -2,4 +2,5 @@
994 usr/lib/pkgconfig
995 usr/include /usr/
996 usr/share/gir-1.0/
997+usr/share/vala/
998 usr/share/gtk-doc
999
1000=== modified file 'debian/libmessaging-menu0.symbols'
1001--- debian/libmessaging-menu0.symbols 2012-09-01 10:35:36 +0000
1002+++ debian/libmessaging-menu0.symbols 2013-07-12 19:50:34 +0000
1003@@ -1,9 +1,11 @@
1004 libmessaging-menu.so.0 libmessaging-menu0 #MINVER#
1005+ messaging_menu_app_append_message@Base 12.10.6-0ubuntu1phablet1
1006 messaging_menu_app_append_source@Base 12.10.0
1007 messaging_menu_app_append_source_with_count@Base 12.10.0
1008 messaging_menu_app_append_source_with_string@Base 12.10.0
1009 messaging_menu_app_append_source_with_time@Base 12.10.0
1010 messaging_menu_app_draw_attention@Base 12.10.0
1011+ messaging_menu_app_get_message@Base 0replaceme
1012 messaging_menu_app_get_type@Base 12.10.0
1013 messaging_menu_app_has_source@Base 12.10.0
1014 messaging_menu_app_insert_source@Base 12.10.0
1015@@ -13,6 +15,8 @@
1016 messaging_menu_app_new@Base 12.10.0
1017 messaging_menu_app_register@Base 12.10.0
1018 messaging_menu_app_remove_attention@Base 12.10.0
1019+ messaging_menu_app_remove_message@Base 12.10.6-0ubuntu1phablet1
1020+ messaging_menu_app_remove_message_by_id@Base 12.10.6-0ubuntu1phablet1
1021 messaging_menu_app_remove_source@Base 12.10.0
1022 messaging_menu_app_set_source_count@Base 12.10.0
1023 messaging_menu_app_set_source_icon@Base 12.10.2
1024@@ -21,3 +25,14 @@
1025 messaging_menu_app_set_source_time@Base 12.10.0
1026 messaging_menu_app_set_status@Base 12.10.0
1027 messaging_menu_app_unregister@Base 12.10.0
1028+ messaging_menu_message_add_action@Base 12.10.6-0ubuntu1phablet3
1029+ messaging_menu_message_get_body@Base 12.10.6-0ubuntu1phablet1
1030+ messaging_menu_message_get_draws_attention@Base 12.10.6-0ubuntu1phablet1
1031+ messaging_menu_message_get_icon@Base 12.10.6-0ubuntu1phablet1
1032+ messaging_menu_message_get_id@Base 12.10.6-0ubuntu1phablet1
1033+ messaging_menu_message_get_subtitle@Base 12.10.6-0ubuntu1phablet1
1034+ messaging_menu_message_get_time@Base 12.10.6-0ubuntu1phablet1
1035+ messaging_menu_message_get_title@Base 12.10.6-0ubuntu1phablet1
1036+ messaging_menu_message_get_type@Base 12.10.6-0ubuntu1phablet1
1037+ messaging_menu_message_new@Base 12.10.6-0ubuntu1phablet1
1038+ messaging_menu_message_set_draws_attention@Base 12.10.6-0ubuntu1phablet1
1039
1040=== added directory 'debian/source'
1041=== added file 'debian/source/format'
1042--- debian/source/format 1970-01-01 00:00:00 +0000
1043+++ debian/source/format 2013-07-12 19:50:34 +0000
1044@@ -0,0 +1,1 @@
1045+1.0
1046
1047=== modified file 'doc/reference/Makefile.am'
1048--- doc/reference/Makefile.am 2013-01-22 20:23:57 +0000
1049+++ doc/reference/Makefile.am 2013-07-12 19:50:34 +0000
1050@@ -11,8 +11,7 @@
1051 CFILE_GLOB = $(top_srcdir)/libmessaging-menu/*.c
1052
1053 IGNORE_HFILES= \
1054- indicator-messages-service.h \
1055- gtupleaction.h
1056+ indicator-messages-service.h
1057
1058 INCLUDES=-I$(top_srcdir)/libmessaging-menu $(GIO_CFLAGS)
1059 GTKDOC_LIBS=$(top_builddir)/libmessaging-menu/libmessaging-menu.la
1060
1061=== modified file 'doc/reference/messaging-menu-docs.xml.in'
1062--- doc/reference/messaging-menu-docs.xml.in 2012-08-29 11:27:54 +0000
1063+++ doc/reference/messaging-menu-docs.xml.in 2013-07-12 19:50:34 +0000
1064@@ -18,7 +18,8 @@
1065
1066 <chapter>
1067 <title>API Reference</title>
1068- <xi:include href="xml/messaging-menu.xml"/>
1069+ <xi:include href="xml/messaging-menu-app.xml" />
1070+ <xi:include href="xml/messaging-menu-message.xml" />
1071 </chapter>
1072
1073 <chapter id="object-tree">
1074
1075=== modified file 'libmessaging-menu/Makefile.am'
1076--- libmessaging-menu/Makefile.am 2012-09-01 08:27:34 +0000
1077+++ libmessaging-menu/Makefile.am 2013-07-12 19:50:34 +0000
1078@@ -4,36 +4,25 @@
1079 libmessaging_menu_ladir = $(includedir)/messaging-menu
1080
1081 libmessaging_menu_la_SOURCES = \
1082- messaging-menu.c \
1083- gtupleaction.c \
1084- gtupleaction.h \
1085- $(BUILT_SOURCES)
1086+ messaging-menu-app.c \
1087+ messaging-menu-message.c
1088
1089 libmessaging_menu_la_HEADERS = \
1090- messaging-menu.h
1091+ messaging-menu-app.h \
1092+ messaging-menu.h \
1093+ messaging-menu-message.h
1094
1095-libmessaging_menu_la_LIBADD = $(GIO_LIBS)
1096+libmessaging_menu_la_LIBADD = \
1097+ $(GIO_LIBS) \
1098+ $(top_builddir)/common/libmessaging-common.la
1099
1100 libmessaging_menu_la_CFLAGS = \
1101+ -I$(top_builddir)/common \
1102 $(GIO_CFLAGS) \
1103 -Wall
1104
1105 libmessaging_menu_la_LDFLAGS = -export-symbols-regex "^messaging_menu_.*"
1106
1107-BUILT_SOURCES = \
1108- indicator-messages-service.c \
1109- indicator-messages-service.h
1110-
1111-CLEANFILES = $(BUILT_SOURCES)
1112-
1113-indicator-messages-service.c: $(top_srcdir)/src/messages-service.xml
1114- $(AM_V_GEN) gdbus-codegen \
1115- --interface-prefix com.canonical.indicator.messages. \
1116- --generate-c-code indicator-messages-service \
1117- --c-namespace IndicatorMessages \
1118- $^
1119-indicator-messages-service.h: indicator-messages-service.c
1120-
1121 pkgconfigdir = $(libdir)/pkgconfig
1122 pkgconfig_DATA = messaging-menu.pc
1123
1124@@ -52,7 +41,11 @@
1125 MessagingMenu_1_0_gir_CFLAGS = $(INCLUDES) $(GIO_CFLAGS)
1126 MessagingMenu_1_0_gir_SCANNERFLAGS = --c-include="messaging-menu.h"
1127 MessagingMenu_1_0_gir_LIBS = libmessaging-menu.la
1128-MessagingMenu_1_0_gir_FILES = messaging-menu.c messaging-menu.h
1129+MessagingMenu_1_0_gir_FILES = \
1130+ messaging-menu-app.c \
1131+ messaging-menu-app.h \
1132+ messaging-menu-message.c \
1133+ messaging-menu-message.h
1134 MessagingMenu_1_0_gir_EXPORT_PACKAGES = messaging-menu
1135 INTROSPECTION_GIRS += MessagingMenu-1.0.gir
1136
1137@@ -62,5 +55,23 @@
1138 typelibdir = $(libdir)/girepository-1.0
1139 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
1140
1141-CLEANFILES +=$(gir_DATA) $(typelib_DATA)
1142+CLEANFILES = $(gir_DATA) $(typelib_DATA)
1143+
1144+
1145+#########################
1146+# VAPI Files
1147+#########################
1148+
1149+if HAVE_VALA
1150+
1151+vapidir = $(datadir)/vala/vapi
1152+vapi_DATA = MessagingMenu-1.0.vapi
1153+
1154+MessagingMenu-1.0.vapi: MessagingMenu-1.0.gir
1155+ $(VALA_API_GEN) --pkg gio-2.0 --library=MessagingMenu-1.0 $<
1156+
1157+CLEANFILES += $(vapi_DATA)
1158+
1159+endif
1160+
1161 endif
1162
1163=== removed file 'libmessaging-menu/gtupleaction.c'
1164--- libmessaging-menu/gtupleaction.c 2012-08-20 21:09:54 +0000
1165+++ libmessaging-menu/gtupleaction.c 1970-01-01 00:00:00 +0000
1166@@ -1,354 +0,0 @@
1167-/*
1168- * Copyright 2012 Canonical Ltd.
1169- *
1170- * This program is free software: you can redistribute it and/or modify it
1171- * under the terms of the GNU General Public License version 3, as
1172- * published by the Free Software Foundation.
1173- *
1174- * This program is distributed in the hope that it will be useful, but
1175- * WITHOUT ANY WARRANTY; without even the implied warranties of
1176- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1177- * PURPOSE. See the GNU General Public License for more details.
1178- *
1179- * You should have received a copy of the GNU General Public License along
1180- * with this program. If not, see <http://www.gnu.org/licenses/>.
1181- *
1182- * Authors:
1183- * Lars Uebernickel <lars.uebernickel@canonical.com>
1184- */
1185-
1186-#include "gtupleaction.h"
1187-
1188-typedef GObjectClass GTupleActionClass;
1189-
1190-struct _GTupleAction
1191-{
1192- GObject parent;
1193-
1194- gchar *name;
1195- GVariantType *type;
1196- gboolean enabled;
1197-
1198- gsize n_children;
1199- GVariant **children;
1200-};
1201-
1202-static void action_interface_init (GActionInterface *iface);
1203-
1204-G_DEFINE_TYPE_WITH_CODE (GTupleAction, g_tuple_action, G_TYPE_OBJECT,
1205- G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, action_interface_init));
1206-
1207-enum
1208-{
1209- PROP_0,
1210- PROP_NAME,
1211- PROP_PARAMETER_TYPE,
1212- PROP_ENABLED,
1213- PROP_STATE_TYPE,
1214- PROP_STATE,
1215- N_PROPERTIES
1216-};
1217-
1218-enum
1219-{
1220- SIGNAL_ACTIVATE,
1221- N_SIGNALS
1222-};
1223-
1224-static GParamSpec *properties[N_PROPERTIES];
1225-static guint signal_ids[N_SIGNALS];
1226-
1227-static const gchar *
1228-g_tuple_action_get_name (GAction *action)
1229-{
1230- GTupleAction *tuple = G_TUPLE_ACTION (action);
1231-
1232- return tuple->name;
1233-}
1234-
1235-static const GVariantType *
1236-g_tuple_action_get_parameter_type (GAction *action)
1237-{
1238- return NULL;
1239-}
1240-
1241-static const GVariantType *
1242-g_tuple_action_get_state_type (GAction *action)
1243-{
1244- GTupleAction *tuple = G_TUPLE_ACTION (action);
1245-
1246- return tuple->type;
1247-}
1248-
1249-static GVariant *
1250-g_tuple_action_get_state_hint (GAction *action)
1251-{
1252- return NULL;
1253-}
1254-
1255-static gboolean
1256-g_tuple_action_get_enabled (GAction *action)
1257-{
1258- GTupleAction *tuple = G_TUPLE_ACTION (action);
1259-
1260- return tuple->enabled;
1261-}
1262-
1263-static GVariant *
1264-g_tuple_action_get_state (GAction *action)
1265-{
1266- GTupleAction *tuple = G_TUPLE_ACTION (action);
1267- GVariant *result;
1268-
1269- result = g_variant_new_tuple (tuple->children, tuple->n_children);
1270- return g_variant_ref_sink (result);
1271-}
1272-
1273-static void
1274-g_tuple_action_set_state (GTupleAction *tuple,
1275- GVariant *state)
1276-{
1277- int i;
1278-
1279- g_return_if_fail (g_variant_type_is_tuple (g_variant_get_type (state)));
1280-
1281- if (tuple->type == NULL)
1282- {
1283- tuple->type = g_variant_type_copy (g_variant_get_type (state));
1284- tuple->n_children = g_variant_n_children (state);
1285- tuple->children = g_new0 (GVariant *, tuple->n_children);
1286- }
1287-
1288- for (i = 0; i < tuple->n_children; i++)
1289- {
1290- if (tuple->children[i])
1291- g_variant_unref (tuple->children[i]);
1292- tuple->children[i] = g_variant_get_child_value (state, i);
1293- }
1294-
1295- g_object_notify_by_pspec (G_OBJECT (tuple), properties[PROP_STATE]);
1296-}
1297-
1298-static void
1299-g_tuple_action_change_state (GAction *action,
1300- GVariant *value)
1301-{
1302- GTupleAction *tuple = G_TUPLE_ACTION (action);
1303-
1304- g_return_if_fail (value != NULL);
1305- g_return_if_fail (g_variant_is_of_type (value, tuple->type));
1306-
1307- g_variant_ref_sink (value);
1308-
1309- /* TODO add a change-state signal similar to GSimpleAction */
1310- g_tuple_action_set_state (tuple, value);
1311-
1312- g_variant_unref (value);
1313-}
1314-
1315-static void
1316-g_tuple_action_activate (GAction *action,
1317- GVariant *parameter)
1318-{
1319- GTupleAction *tuple = G_TUPLE_ACTION (action);
1320-
1321- g_return_if_fail (parameter == NULL);
1322-
1323- if (tuple->enabled)
1324- g_signal_emit (tuple, signal_ids[SIGNAL_ACTIVATE], 0, NULL);
1325-}
1326-
1327-static void
1328-g_tuple_action_get_property (GObject *object,
1329- guint prop_id,
1330- GValue *value,
1331- GParamSpec *pspec)
1332-{
1333- GAction *action = G_ACTION (object);
1334-
1335- switch (prop_id)
1336- {
1337- case PROP_NAME:
1338- g_value_set_string (value, g_tuple_action_get_name (action));
1339- break;
1340-
1341- case PROP_PARAMETER_TYPE:
1342- g_value_set_boxed (value, g_tuple_action_get_parameter_type (action));
1343- break;
1344-
1345- case PROP_ENABLED:
1346- g_value_set_boolean (value, g_tuple_action_get_enabled (action));
1347- break;
1348-
1349- case PROP_STATE_TYPE:
1350- g_value_set_boxed (value, g_tuple_action_get_state_type (action));
1351- break;
1352-
1353- case PROP_STATE:
1354- g_value_take_variant (value, g_tuple_action_get_state (action));
1355- break;
1356-
1357- default:
1358- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1359- }
1360-}
1361-
1362-static void
1363-g_tuple_action_set_property (GObject *object,
1364- guint prop_id,
1365- const GValue *value,
1366- GParamSpec *pspec)
1367-{
1368- GTupleAction *tuple = G_TUPLE_ACTION (object);
1369-
1370- switch (prop_id)
1371- {
1372- case PROP_NAME:
1373- tuple->name = g_value_dup_string (value);
1374- g_object_notify_by_pspec (object, properties[PROP_NAME]);
1375- break;
1376-
1377- case PROP_ENABLED:
1378- tuple->enabled = g_value_get_boolean (value);
1379- g_object_notify_by_pspec (object, properties[PROP_ENABLED]);
1380- break;
1381-
1382- case PROP_STATE:
1383- g_tuple_action_set_state (tuple, g_value_get_variant (value));
1384- break;
1385-
1386- default:
1387- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1388- }
1389-}
1390-
1391-static void
1392-g_tuple_action_finalize (GObject *object)
1393-{
1394- GTupleAction *tuple = G_TUPLE_ACTION (object);
1395- int i;
1396-
1397- g_free (tuple->name);
1398- g_variant_type_free (tuple->type);
1399-
1400- for (i = 0; i < tuple->n_children; i++)
1401- g_variant_unref (tuple->children[i]);
1402-
1403- g_free (tuple->children);
1404-
1405- G_OBJECT_CLASS (g_tuple_action_parent_class)->finalize (object);
1406-}
1407-
1408-static void
1409-action_interface_init (GActionInterface *iface)
1410-{
1411- iface->get_name = g_tuple_action_get_name;
1412- iface->get_parameter_type = g_tuple_action_get_parameter_type;
1413- iface->get_state_type = g_tuple_action_get_state_type;
1414- iface->get_state_hint = g_tuple_action_get_state_hint;
1415- iface->get_enabled = g_tuple_action_get_enabled;
1416- iface->get_state = g_tuple_action_get_state;
1417- iface->change_state = g_tuple_action_change_state;
1418- iface->activate = g_tuple_action_activate;
1419-}
1420-
1421-static void
1422-g_tuple_action_class_init (GTupleActionClass *class)
1423-{
1424- GObjectClass *object_class = G_OBJECT_CLASS (class);
1425-
1426- object_class->get_property = g_tuple_action_get_property;
1427- object_class->set_property = g_tuple_action_set_property;
1428- object_class->finalize = g_tuple_action_finalize;
1429-
1430- properties[PROP_NAME] = g_param_spec_string ("name",
1431- "Name",
1432- "The name of the action",
1433- NULL,
1434- G_PARAM_READWRITE |
1435- G_PARAM_CONSTRUCT_ONLY |
1436- G_PARAM_STATIC_STRINGS);
1437-
1438- properties[PROP_PARAMETER_TYPE] = g_param_spec_boxed ("parameter-type",
1439- "Parameter Type",
1440- "The variant type passed to activate",
1441- G_TYPE_VARIANT_TYPE,
1442- G_PARAM_READABLE |
1443- G_PARAM_STATIC_STRINGS);
1444-
1445- properties[PROP_ENABLED] = g_param_spec_boolean ("enabled",
1446- "Enabled",
1447- "Whether the action can be activated",
1448- TRUE,
1449- G_PARAM_READWRITE |
1450- G_PARAM_STATIC_STRINGS);
1451-
1452- properties[PROP_STATE_TYPE] = g_param_spec_boxed ("state-type",
1453- "State Type",
1454- "The variant type of the state, must be a tuple",
1455- G_TYPE_VARIANT_TYPE,
1456- G_PARAM_READABLE |
1457- G_PARAM_STATIC_STRINGS);
1458-
1459- properties[PROP_STATE] = g_param_spec_variant ("state",
1460- "State",
1461- "The state of the action",
1462- G_VARIANT_TYPE_TUPLE,
1463- NULL,
1464- G_PARAM_READWRITE |
1465- G_PARAM_STATIC_STRINGS);
1466-
1467- g_object_class_install_properties (object_class, N_PROPERTIES, properties);
1468-
1469- signal_ids[SIGNAL_ACTIVATE] = g_signal_new ("activate",
1470- G_TYPE_TUPLE_ACTION,
1471- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
1472- 0, NULL, NULL,
1473- g_cclosure_marshal_VOID__VARIANT,
1474- G_TYPE_NONE, 1,
1475- G_TYPE_VARIANT);
1476-}
1477-
1478-static void
1479-g_tuple_action_init (GTupleAction *action)
1480-{
1481- action->enabled = TRUE;
1482-}
1483-
1484-GTupleAction *
1485-g_tuple_action_new (const gchar *name,
1486- GVariant *initial_state)
1487-{
1488- const GVariantType *type;
1489-
1490- g_return_val_if_fail (name != NULL, NULL);
1491- g_return_val_if_fail (initial_state != NULL, NULL);
1492-
1493- type = g_variant_get_type (initial_state);
1494- g_return_val_if_fail (g_variant_type_is_tuple (type), NULL);
1495-
1496- return g_object_new (G_TYPE_TUPLE_ACTION,
1497- "name", name,
1498- "state", initial_state,
1499- NULL);
1500-}
1501-
1502-void
1503-g_tuple_action_set_child (GTupleAction *action,
1504- gsize index,
1505- GVariant *value)
1506-{
1507- const GVariantType *type;
1508-
1509- g_return_if_fail (G_IS_TUPLE_ACTION (action));
1510- g_return_if_fail (index < action->n_children);
1511- g_return_if_fail (value != NULL);
1512-
1513- type = g_variant_get_type (value);
1514- g_return_if_fail (g_variant_is_of_type (value, type));
1515-
1516- g_variant_unref (action->children[index]);
1517- action->children[index] = g_variant_ref_sink (value);
1518-
1519- g_object_notify_by_pspec (G_OBJECT (action), properties[PROP_STATE]);
1520-}
1521
1522=== removed file 'libmessaging-menu/gtupleaction.h'
1523--- libmessaging-menu/gtupleaction.h 2012-06-28 14:07:17 +0000
1524+++ libmessaging-menu/gtupleaction.h 1970-01-01 00:00:00 +0000
1525@@ -1,40 +0,0 @@
1526-/*
1527- * Copyright 2012 Canonical Ltd.
1528- *
1529- * This program is free software: you can redistribute it and/or modify it
1530- * under the terms of the GNU General Public License version 3, as
1531- * published by the Free Software Foundation.
1532- *
1533- * This program is distributed in the hope that it will be useful, but
1534- * WITHOUT ANY WARRANTY; without even the implied warranties of
1535- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1536- * PURPOSE. See the GNU General Public License for more details.
1537- *
1538- * You should have received a copy of the GNU General Public License along
1539- * with this program. If not, see <http://www.gnu.org/licenses/>.
1540- *
1541- * Authors:
1542- * Lars Uebernickel <lars.uebernickel@canonical.com>
1543- */
1544-
1545-#ifndef __g_tuple_action_h__
1546-#define __g_tuple_action_h__
1547-
1548-#include <gio/gio.h>
1549-
1550-#define G_TYPE_TUPLE_ACTION (g_tuple_action_get_type ())
1551-#define G_TUPLE_ACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TUPLE_ACTION, GTupleAction))
1552-#define G_IS_TUPLE_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TUPLE_ACTION))
1553-
1554-typedef struct _GTupleAction GTupleAction;
1555-
1556-GType g_tuple_action_get_type (void) G_GNUC_CONST;
1557-
1558-GTupleAction * g_tuple_action_new (const gchar *name,
1559- GVariant *initial_state);
1560-
1561-void g_tuple_action_set_child (GTupleAction *action,
1562- gsize index,
1563- GVariant *value);
1564-
1565-#endif
1566
1567=== renamed file 'libmessaging-menu/messaging-menu.c' => 'libmessaging-menu/messaging-menu-app.c'
1568--- libmessaging-menu/messaging-menu.c 2013-06-07 22:15:28 +0000
1569+++ libmessaging-menu/messaging-menu-app.c 2013-07-12 19:50:34 +0000
1570@@ -17,10 +17,12 @@
1571 * Lars Uebernickel <lars.uebernickel@canonical.com>
1572 */
1573
1574-#include "messaging-menu.h"
1575+#include "messaging-menu-app.h"
1576 #include "indicator-messages-service.h"
1577+#include "indicator-messages-application.h"
1578
1579 #include <gio/gdesktopappinfo.h>
1580+#include <string.h>
1581
1582 /**
1583 * SECTION:messaging-menu
1584@@ -102,14 +104,14 @@
1585 int registered; /* -1 for unknown */
1586 MessagingMenuStatus status;
1587 gboolean status_set;
1588- GSimpleActionGroup *source_actions;
1589- GMenu *menu;
1590 GDBusConnection *bus;
1591
1592+ GHashTable *messages;
1593+ GList *sources;
1594+ IndicatorMessagesApplication *app_interface;
1595+
1596 IndicatorMessagesService *messages_service;
1597 guint watch_id;
1598- guint action_export_id;
1599- guint menu_export_id;
1600
1601 GCancellable *cancellable;
1602 };
1603@@ -133,10 +135,61 @@
1604
1605 static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" };
1606
1607+typedef struct
1608+{
1609+ gchar *id;
1610+ GIcon *icon;
1611+ gchar *label;
1612+
1613+ guint32 count;
1614+ gint64 time;
1615+ gchar *string;
1616+ gboolean draws_attention;
1617+} Source;
1618+
1619 static void global_status_changed (IndicatorMessagesService *service,
1620 const gchar *status_str,
1621 gpointer user_data);
1622
1623+/* in messaging-menu-message.c */
1624+GVariant * _messaging_menu_message_to_variant (MessagingMenuMessage *msg);
1625+
1626+static void
1627+source_free (gpointer data)
1628+{
1629+ Source *source = data;
1630+
1631+ if (source)
1632+ {
1633+ g_free (source->id);
1634+ g_clear_object (&source->icon);
1635+ g_free (source->label);
1636+ g_free (source->string);
1637+ g_slice_free (Source, source);
1638+ }
1639+}
1640+
1641+static GVariant *
1642+source_to_variant (Source *source)
1643+{
1644+ GVariant *v;
1645+ gchar *iconstr;
1646+
1647+ iconstr = source->icon ? g_icon_to_string (source->icon) : NULL;
1648+
1649+ v = g_variant_new ("(sssuxsb)", source->id,
1650+ source->label,
1651+ iconstr ? iconstr : "",
1652+ source->count,
1653+ source->time,
1654+ source->string ? source->string : "",
1655+ source->draws_attention);
1656+
1657+ g_free (iconstr);
1658+
1659+ return v;
1660+}
1661+
1662 static gchar *
1663 messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
1664 {
1665@@ -155,18 +208,14 @@
1666 }
1667
1668 static void
1669-export_menus_and_actions (GObject *source,
1670- GAsyncResult *res,
1671- gpointer user_data)
1672+messaging_menu_app_got_bus (GObject *source,
1673+ GAsyncResult *res,
1674+ gpointer user_data)
1675 {
1676 MessagingMenuApp *app = user_data;
1677 GError *error = NULL;
1678 gchar *object_path;
1679
1680- object_path = messaging_menu_app_get_dbus_object_path (app);
1681- if (!object_path)
1682- return;
1683-
1684 app->bus = g_bus_get_finish (res, &error);
1685 if (app->bus == NULL)
1686 {
1687@@ -175,23 +224,13 @@
1688 return;
1689 }
1690
1691- app->action_export_id = g_dbus_connection_export_action_group (app->bus,
1692- object_path,
1693- G_ACTION_GROUP (app->source_actions),
1694- &error);
1695- if (!app->action_export_id)
1696- {
1697- g_warning ("unable to export action group: %s", error->message);
1698- g_clear_error (&error);
1699- }
1700+ object_path = messaging_menu_app_get_dbus_object_path (app);
1701
1702- app->menu_export_id = g_dbus_connection_export_menu_model (app->bus,
1703- object_path,
1704- G_MENU_MODEL (app->menu),
1705- &error);
1706- if (!app->menu_export_id)
1707+ if (object_path &&
1708+ !g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (app->app_interface),
1709+ app->bus, object_path, &error))
1710 {
1711- g_warning ("unable to export menu: %s", error->message);
1712+ g_warning ("unable to export application interface: %s", error->message);
1713 g_clear_error (&error);
1714 }
1715
1716@@ -214,7 +253,7 @@
1717
1718 g_bus_get (G_BUS_TYPE_SESSION,
1719 app->cancellable,
1720- export_menus_and_actions,
1721+ messaging_menu_app_got_bus,
1722 app);
1723 }
1724
1725@@ -248,20 +287,6 @@
1726 {
1727 MessagingMenuApp *app = MESSAGING_MENU_APP (object);
1728
1729- if (app->bus)
1730- {
1731- if (app->action_export_id > 0)
1732- g_dbus_connection_unexport_action_group (app->bus, app->action_export_id);
1733-
1734- if (app->menu_export_id > 0)
1735- g_dbus_connection_unexport_menu_model (app->bus, app->menu_export_id);
1736-
1737- app->action_export_id = 0;
1738- app->menu_export_id = 0;
1739- g_object_unref (app->bus);
1740- app->bus = NULL;
1741- }
1742-
1743 if (app->watch_id > 0)
1744 {
1745 g_bus_unwatch_name (app->watch_id);
1746@@ -287,9 +312,14 @@
1747 g_clear_object (&app->messages_service);
1748 }
1749
1750+ g_clear_pointer (&app->messages, g_hash_table_unref);
1751+
1752+ g_list_free_full (app->sources, source_free);
1753+ app->sources = NULL;
1754+
1755+ g_clear_object (&app->app_interface);
1756 g_clear_object (&app->appinfo);
1757- g_clear_object (&app->source_actions);
1758- g_clear_object (&app->menu);
1759+ g_clear_object (&app->bus);
1760
1761 G_OBJECT_CLASS (messaging_menu_app_parent_class)->dispose (object);
1762 }
1763@@ -420,6 +450,168 @@
1764 }
1765 }
1766
1767+static gboolean
1768+messaging_menu_app_list_sources (IndicatorMessagesApplication *app_interface,
1769+ GDBusMethodInvocation *invocation,
1770+ gpointer user_data)
1771+{
1772+ MessagingMenuApp *app = user_data;
1773+ GVariantBuilder builder;
1774+ GList *it;
1775+
1776+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssuxsb)"));
1777+
1778+ for (it = app->sources; it; it = it->next)
1779+ g_variant_builder_add_value (&builder, source_to_variant (it->data));
1780+
1781+ indicator_messages_application_complete_list_sources (app_interface,
1782+ invocation,
1783+ g_variant_builder_end (&builder));
1784+
1785+ return TRUE;
1786+}
1787+
1788+static gint
1789+compare_source_id (gconstpointer a,
1790+ gconstpointer b)
1791+{
1792+ const Source *source = a;
1793+ const gchar *id = b;
1794+
1795+ return strcmp (source->id, id);
1796+}
1797+
1798+static gboolean
1799+messaging_menu_app_remove_source_internal (MessagingMenuApp *app,
1800+ const gchar *source_id)
1801+{
1802+ GList *node;
1803+
1804+ node = g_list_find_custom (app->sources, source_id, compare_source_id);
1805+ if (node)
1806+ {
1807+ source_free (node->data);
1808+ app->sources = g_list_delete_link (app->sources, node);
1809+ return TRUE;
1810+ }
1811+
1812+ return FALSE;
1813+}
1814+
1815+static gboolean
1816+messaging_menu_app_remove_message_internal (MessagingMenuApp *app,
1817+ const gchar *message_id)
1818+{
1819+ return g_hash_table_remove (app->messages, message_id);
1820+}
1821+
1822+static gboolean
1823+messaging_menu_app_activate_source (IndicatorMessagesApplication *app_interface,
1824+ GDBusMethodInvocation *invocation,
1825+ const gchar *source_id,
1826+ gpointer user_data)
1827+{
1828+ MessagingMenuApp *app = user_data;
1829+ GQuark q = g_quark_from_string (source_id);
1830+
1831+ /* Activate implies removing the source, no need for SourceRemoved */
1832+ if (messaging_menu_app_remove_source_internal (app, source_id))
1833+ g_signal_emit (app, signals[ACTIVATE_SOURCE], q, source_id);
1834+
1835+ indicator_messages_application_complete_activate_source (app_interface, invocation);
1836+
1837+ return TRUE;
1838+}
1839+
1840+static gboolean
1841+messaging_menu_app_list_messages (IndicatorMessagesApplication *app_interface,
1842+ GDBusMethodInvocation *invocation,
1843+ gpointer user_data)
1844+{
1845+ MessagingMenuApp *app = user_data;
1846+ GVariantBuilder builder;
1847+ GHashTableIter iter;
1848+ MessagingMenuMessage *message;
1849+
1850+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxaa{sv}b)"));
1851+
1852+ g_hash_table_iter_init (&iter, app->messages);
1853+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
1854+ g_variant_builder_add_value (&builder, _messaging_menu_message_to_variant (message));
1855+
1856+ indicator_messages_application_complete_list_messages (app_interface,
1857+ invocation,
1858+ g_variant_builder_end (&builder));
1859+
1860+ return TRUE;
1861+}
1862+
1863+static gboolean
1864+messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface,
1865+ GDBusMethodInvocation *invocation,
1866+ const gchar *message_id,
1867+ const gchar *action_id,
1868+ GVariant *params,
1869+ gpointer user_data)
1870+{
1871+ MessagingMenuApp *app = user_data;
1872+ MessagingMenuMessage *msg;
1873+
1874+ msg = g_hash_table_lookup (app->messages, message_id);
1875+ if (msg)
1876+ {
1877+ if (*action_id)
1878+ {
1879+ gchar *signal;
1880+
1881+ signal = g_strconcat ("activate::", action_id, NULL);
1882+
1883+ if (g_variant_n_children (params))
1884+ {
1885+ GVariant *param;
1886+
1887+ g_variant_get_child (params, 0, "v", &param);
1888+ g_signal_emit_by_name (msg, signal, action_id, param);
1889+
1890+ g_variant_unref (param);
1891+ }
1892+ else
1893+ g_signal_emit_by_name (msg, signal, action_id, NULL);
1894+
1895+ g_free (signal);
1896+ }
1897+ else
1898+ g_signal_emit_by_name (msg, "activate", NULL, NULL);
1899+
1900+
1901+ /* Activate implies removing the message, no need for MessageRemoved */
1902+ messaging_menu_app_remove_message_internal (app, message_id);
1903+ }
1904+
1905+ indicator_messages_application_complete_activate_message (app_interface, invocation);
1906+
1907+ return TRUE;
1908+}
1909+
1910+static gboolean
1911+messaging_menu_app_dismiss (IndicatorMessagesApplication *app_interface,
1912+ GDBusMethodInvocation *invocation,
1913+ const gchar * const *sources,
1914+ const gchar * const *messages,
1915+ gpointer user_data)
1916+{
1917+ MessagingMenuApp *app = user_data;
1918+ const gchar * const *it;
1919+
1920+ for (it = sources; *it; it++)
1921+ messaging_menu_app_remove_source_internal (app, *it);
1922+
1923+ for (it = messages; *it; it++)
1924+ messaging_menu_app_remove_message_internal (app, *it);
1925+
1926+ return TRUE;
1927+}
1928+
1929 static void
1930 messaging_menu_app_init (MessagingMenuApp *app)
1931 {
1932@@ -427,15 +619,21 @@
1933 app->status_set = FALSE;
1934 app->bus = NULL;
1935
1936- app->action_export_id = 0;
1937- app->menu_export_id = 0;
1938-
1939- app->cancellable = g_cancellable_new ();
1940-
1941- app->source_actions = g_simple_action_group_new ();
1942- app->menu = g_menu_new ();
1943-
1944- app->cancellable = g_cancellable_new ();
1945+ app->cancellable = g_cancellable_new ();
1946+
1947+ app->app_interface = indicator_messages_application_skeleton_new ();
1948+ g_signal_connect (app->app_interface, "handle-list-sources",
1949+ G_CALLBACK (messaging_menu_app_list_sources), app);
1950+ g_signal_connect (app->app_interface, "handle-activate-source",
1951+ G_CALLBACK (messaging_menu_app_activate_source), app);
1952+ g_signal_connect (app->app_interface, "handle-list-messages",
1953+ G_CALLBACK (messaging_menu_app_list_messages), app);
1954+ g_signal_connect (app->app_interface, "handle-activate-message",
1955+ G_CALLBACK (messaging_menu_app_activate_message), app);
1956+ g_signal_connect (app->app_interface, "handle-dismiss",
1957+ G_CALLBACK (messaging_menu_app_dismiss), app);
1958+
1959+ app->messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1960
1961 app->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
1962 "com.canonical.indicator.messages",
1963@@ -608,40 +806,61 @@
1964 g_signal_emit (app, signals[STATUS_CHANGED], 0, status);
1965 }
1966
1967-static void
1968-source_action_activated (GSimpleAction *action,
1969- GVariant *parameter,
1970- gpointer user_data)
1971-{
1972- MessagingMenuApp *app = user_data;
1973- const gchar *name = g_action_get_name (G_ACTION (action));
1974- GQuark q = g_quark_from_string (name);
1975-
1976- messaging_menu_app_remove_source (app, name);
1977-
1978- g_signal_emit (app, signals[ACTIVATE_SOURCE], q, name);
1979-}
1980-
1981-static void
1982-messaging_menu_app_insert_source_action (MessagingMenuApp *app,
1983- gint position,
1984- const gchar *id,
1985- GIcon *icon,
1986- const gchar *label,
1987- GVariant *state)
1988-{
1989- GSimpleAction *action;
1990- GMenuItem *menuitem;
1991+static Source *
1992+messaging_menu_app_lookup_source (MessagingMenuApp *app,
1993+ const gchar *id)
1994+{
1995+ GList *node;
1996+
1997+ node = g_list_find_custom (app->sources, id, compare_source_id);
1998+
1999+ return node ? node->data : NULL;
2000+}
2001+
2002+static Source *
2003+messaging_menu_app_get_source (MessagingMenuApp *app,
2004+ const gchar *id)
2005+{
2006+ Source *source;
2007+
2008+ source = messaging_menu_app_lookup_source (app, id);
2009+ if (!source)
2010+ g_warning ("a source with id '%s' doesn't exist", id);
2011+
2012+ return source;
2013+}
2014+
2015+static void
2016+messaging_menu_app_notify_source_changed (MessagingMenuApp *app,
2017+ Source *source)
2018+{
2019+ indicator_messages_application_emit_source_changed (app->app_interface,
2020+ source_to_variant (source));
2021+}
2022+
2023+static void
2024+messaging_menu_app_insert_source_internal (MessagingMenuApp *app,
2025+ gint position,
2026+ const gchar *id,
2027+ GIcon *icon,
2028+ const gchar *label,
2029+ guint count,
2030+ gint64 time,
2031+ const gchar *string)
2032+{
2033+ Source *source;
2034
2035 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2036 g_return_if_fail (id != NULL);
2037+ g_return_if_fail (label != NULL);
2038
2039- if (g_simple_action_group_lookup (app->source_actions, id))
2040+ if (messaging_menu_app_lookup_source (app, id))
2041 {
2042 g_warning ("a source with id '%s' already exists", id);
2043 return;
2044 }
2045
2046+<<<<<<< TREE
2047 action = g_simple_action_new_stateful (id, NULL, state);
2048 g_signal_connect (action, "activate",
2049 G_CALLBACK (source_action_activated), app);
2050@@ -651,7 +870,13 @@
2051 menuitem = g_menu_item_new (label, NULL);
2052 g_menu_item_set_action_and_target_value (menuitem, id, NULL);
2053 g_menu_item_set_attribute (menuitem, "x-canonical-type", "s", "ImSourceMenuItem");
2054+=======
2055+ source = g_slice_new0 (Source);
2056+ source->id = g_strdup (id);
2057+ source->label = g_strdup (label);
2058+>>>>>>> MERGE-SOURCE
2059 if (icon)
2060+<<<<<<< TREE
2061 {
2062 gchar *iconstr = g_icon_to_string (icon);
2063 g_menu_item_set_attribute (menuitem, "x-canonical-icon", "s", iconstr);
2064@@ -726,6 +951,17 @@
2065 g_simple_action_set_state (action, new_state);
2066
2067 g_variant_unref (state);
2068+=======
2069+ source->icon = g_object_ref (icon);
2070+ source->count = count;
2071+ source->time = time;
2072+ source->string = g_strdup (string);
2073+ app->sources = g_list_insert (app->sources, source, position);
2074+
2075+ indicator_messages_application_emit_source_added (app->app_interface,
2076+ position,
2077+ source_to_variant (source));
2078+>>>>>>> MERGE-SOURCE
2079 }
2080
2081 /**
2082@@ -802,8 +1038,7 @@
2083 const gchar *label,
2084 guint count)
2085 {
2086- messaging_menu_app_insert_source_action (app, position, id, icon, label,
2087- g_variant_new ("(uxsb)", count, 0, "", FALSE));
2088+ messaging_menu_app_insert_source_internal (app, position, id, icon, label, count, 0, "");
2089 }
2090
2091 /**
2092@@ -857,8 +1092,7 @@
2093 const gchar *label,
2094 gint64 time)
2095 {
2096- messaging_menu_app_insert_source_action (app, position, id, icon, label,
2097- g_variant_new ("(uxsb)", 0, time, "", FALSE));
2098+ messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, time, "");
2099 }
2100
2101 /**
2102@@ -914,8 +1148,7 @@
2103 const gchar *label,
2104 const gchar *str)
2105 {
2106- messaging_menu_app_insert_source_action (app, position, id, icon, label,
2107- g_variant_new ("(uxsb)", 0, 0, str, FALSE));
2108+ messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, 0, str);
2109 }
2110
2111 /**
2112@@ -955,34 +1188,11 @@
2113 messaging_menu_app_remove_source (MessagingMenuApp *app,
2114 const gchar *source_id)
2115 {
2116- int n_items;
2117- int i;
2118-
2119 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2120 g_return_if_fail (source_id != NULL);
2121
2122- if (g_simple_action_group_lookup (app->source_actions, source_id) == NULL)
2123- return;
2124-
2125- n_items = g_menu_model_get_n_items (G_MENU_MODEL (app->menu));
2126- for (i = 0; i < n_items; i++)
2127- {
2128- gchar *action;
2129-
2130- if (g_menu_model_get_item_attribute (G_MENU_MODEL (app->menu), i,
2131- "action", "s", &action))
2132- {
2133- if (!g_strcmp0 (action, source_id))
2134- {
2135- g_menu_remove (app->menu, i);
2136- break;
2137- }
2138-
2139- g_free (action);
2140- }
2141- }
2142-
2143- g_simple_action_group_remove (app->source_actions, source_id);
2144+ if (messaging_menu_app_remove_source_internal (app, source_id))
2145+ indicator_messages_application_emit_source_removed (app->app_interface, source_id);
2146 }
2147
2148 /**
2149@@ -999,46 +1209,7 @@
2150 g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), FALSE);
2151 g_return_val_if_fail (source_id != NULL, FALSE);
2152
2153- return g_simple_action_group_lookup (app->source_actions, source_id) != NULL;
2154-}
2155-
2156-static GMenuItem *
2157-g_menu_find_item_with_action (GMenu *menu,
2158- const gchar *action,
2159- gint *out_pos)
2160-{
2161- gint i;
2162- gint n_elements;
2163- GMenuItem *item = NULL;
2164-
2165- n_elements = g_menu_model_get_n_items (G_MENU_MODEL (menu));
2166-
2167- for (i = 0; i < n_elements && item == NULL; i++)
2168- {
2169- GVariant *attr;
2170-
2171- item = g_menu_item_new_from_model (G_MENU_MODEL (menu), i);
2172- attr = g_menu_item_get_attribute_value (item, G_MENU_ATTRIBUTE_ACTION, G_VARIANT_TYPE_STRING);
2173-
2174- if (!g_str_equal (action, g_variant_get_string (attr, NULL)))
2175- g_clear_object (&item);
2176-
2177- g_variant_unref (attr);
2178- }
2179-
2180- if (item && out_pos)
2181- *out_pos = i - 1;
2182-
2183- return item;
2184-}
2185-
2186-static void
2187-g_menu_replace_item (GMenu *menu,
2188- gint pos,
2189- GMenuItem *item)
2190-{
2191- g_menu_remove (menu, pos);
2192- g_menu_insert_item (menu, pos, item);
2193+ return messaging_menu_app_lookup_source (app, source_id) != NULL;
2194 }
2195
2196 /**
2197@@ -1054,21 +1225,19 @@
2198 const gchar *source_id,
2199 const gchar *label)
2200 {
2201- gint pos;
2202- GMenuItem *item;
2203+ Source *source;
2204
2205 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2206 g_return_if_fail (source_id != NULL);
2207 g_return_if_fail (label != NULL);
2208
2209- item = g_menu_find_item_with_action (app->menu, source_id, &pos);
2210- if (item == NULL)
2211- return;
2212-
2213- g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_LABEL, "s", label);
2214- g_menu_replace_item (app->menu, pos, item);
2215-
2216- g_object_unref (item);
2217+ source = messaging_menu_app_get_source (app, source_id);
2218+ if (source)
2219+ {
2220+ g_free (source->label);
2221+ source->label = g_strdup (label);
2222+ messaging_menu_app_notify_source_changed (app, source);
2223+ }
2224 }
2225
2226 /**
2227@@ -1084,33 +1253,19 @@
2228 const gchar *source_id,
2229 GIcon *icon)
2230 {
2231- gint pos;
2232- GMenuItem *item;
2233+ Source *source;
2234
2235 g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2236 g_return_if_fail (source_id != NULL);
2237
2238- item = g_menu_find_item_with_action (app->menu, source_id, &pos);
2239- if (item == NULL)
2240- return;
2241-
2242- if (icon)
2243- {
2244- gchar *iconstr;
2245-
2246- iconstr = g_icon_to_string (icon);
2247- g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr);
2248-
2249- g_free (iconstr);
2250- }
2251- else
2252- {
2253- g_menu_item_set_attribute_value (item, "x-canonical-icon", NULL);
2254- }
2255-
2256- g_menu_replace_item (app->menu, pos, item);
2257-
2258- g_object_unref (item);
2259+ source = messaging_menu_app_get_source (app, source_id);
2260+ if (source)
2261+ {
2262+ g_clear_object (&source->icon);
2263+ if (icon)
2264+ source->icon = g_object_ref (icon);
2265+ messaging_menu_app_notify_source_changed (app, source);
2266+ }
2267 }
2268
2269 /**
2270@@ -1125,7 +1280,17 @@
2271 const gchar *source_id,
2272 guint count)
2273 {
2274- messaging_menu_app_set_source_action (app, source_id, count, 0, "");
2275+ Source *source;
2276+
2277+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2278+ g_return_if_fail (source_id != NULL);
2279+
2280+ source = messaging_menu_app_get_source (app, source_id);
2281+ if (source)
2282+ {
2283+ source->count = count;
2284+ messaging_menu_app_notify_source_changed (app, source);
2285+ }
2286 }
2287
2288 /**
2289@@ -1141,7 +1306,17 @@
2290 const gchar *source_id,
2291 gint64 time)
2292 {
2293- messaging_menu_app_set_source_action (app, source_id, 0, time, "");
2294+ Source *source;
2295+
2296+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2297+ g_return_if_fail (source_id != NULL);
2298+
2299+ source = messaging_menu_app_get_source (app, source_id);
2300+ if (source)
2301+ {
2302+ source->time = time;
2303+ messaging_menu_app_notify_source_changed (app, source);
2304+ }
2305 }
2306
2307 /**
2308@@ -1157,7 +1332,18 @@
2309 const gchar *source_id,
2310 const gchar *str)
2311 {
2312- messaging_menu_app_set_source_action (app, source_id, 0, 0, str);
2313+ Source *source;
2314+
2315+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2316+ g_return_if_fail (source_id != NULL);
2317+
2318+ source = messaging_menu_app_get_source (app, source_id);
2319+ if (source)
2320+ {
2321+ g_free (source->string);
2322+ source->string = g_strdup (str);
2323+ messaging_menu_app_notify_source_changed (app, source);
2324+ }
2325 }
2326
2327 /**
2328@@ -1175,7 +1361,17 @@
2329 messaging_menu_app_draw_attention (MessagingMenuApp *app,
2330 const gchar *source_id)
2331 {
2332- messaging_menu_app_set_draws_attention (app, source_id, TRUE);
2333+ Source *source;
2334+
2335+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2336+ g_return_if_fail (source_id != NULL);
2337+
2338+ source = messaging_menu_app_get_source (app, source_id);
2339+ if (source)
2340+ {
2341+ source->draws_attention = TRUE;
2342+ messaging_menu_app_notify_source_changed (app, source);
2343+ }
2344 }
2345
2346 /**
2347@@ -1196,5 +1392,135 @@
2348 messaging_menu_app_remove_attention (MessagingMenuApp *app,
2349 const gchar *source_id)
2350 {
2351+<<<<<<< TREE
2352 messaging_menu_app_set_draws_attention (app, source_id, FALSE);
2353+=======
2354+ Source *source;
2355+
2356+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2357+ g_return_if_fail (source_id != NULL);
2358+
2359+ source = messaging_menu_app_get_source (app, source_id);
2360+ if (source)
2361+ {
2362+ source->draws_attention = FALSE;
2363+ messaging_menu_app_notify_source_changed (app, source);
2364+ }
2365+}
2366+
2367+/**
2368+ * messaging_menu_app_append_message:
2369+ * @app: a #MessagingMenuApp
2370+ * @msg: the #MessagingMenuMessage to append
2371+ * @source_id: (allow-none): the source id to which @msg is added, or NULL
2372+ * @notify: whether a notification bubble should be shown for this
2373+ * message
2374+ *
2375+ * Appends @msg to the source with id @source_id of @app. The messaging
2376+ * menu might not display this message immediately if other messages are
2377+ * queued before this one.
2378+ *
2379+ * If @source_id has a count associated with it, that count will be
2380+ * increased by one.
2381+ *
2382+ * If @source_id is %NULL, @msg won't be associated with a source.
2383+ */
2384+void
2385+messaging_menu_app_append_message (MessagingMenuApp *app,
2386+ MessagingMenuMessage *msg,
2387+ const gchar *source_id,
2388+ gboolean notify)
2389+{
2390+ const gchar *id;
2391+
2392+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2393+ g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
2394+
2395+ id = messaging_menu_message_get_id (msg);
2396+
2397+ if (g_hash_table_lookup (app->messages, id))
2398+ {
2399+ g_warning ("a message with id '%s' already exists", id);
2400+ return;
2401+ }
2402+
2403+ g_hash_table_insert (app->messages, g_strdup (id), g_object_ref (msg));
2404+ indicator_messages_application_emit_message_added (app->app_interface,
2405+ _messaging_menu_message_to_variant (msg));
2406+
2407+ if (source_id)
2408+ {
2409+ Source *source;
2410+
2411+ source = messaging_menu_app_get_source (app, source_id);
2412+ if (source && source->count >= 0)
2413+ {
2414+ source->count++;
2415+ messaging_menu_app_notify_source_changed (app, source);
2416+ }
2417+ }
2418+}
2419+
2420+/**
2421+ * messaging_menu_app_get_message:
2422+ * @app: a #MessagingMenuApp
2423+ * @id: id of the message to retrieve
2424+ *
2425+ * Retrieves the message with @id, that was added with
2426+ * messaging_menu_app_append_message().
2427+ *
2428+ * Returns: (transfer none) (allow-none): the #MessagingMenuApp with
2429+ * @id, or %NULL
2430+ */
2431+MessagingMenuMessage *
2432+messaging_menu_app_get_message (MessagingMenuApp *app,
2433+ const gchar *id)
2434+{
2435+ g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), NULL);
2436+ g_return_val_if_fail (id != NULL, NULL);
2437+
2438+ return g_hash_table_lookup (app->messages, id);
2439+}
2440+
2441+/**
2442+ * messaging_menu_app_remove_message:
2443+ * @app: a #MessagingMenuApp
2444+ * @msg: the #MessagingMenuMessage to remove
2445+ *
2446+ * Removes @msg from @app.
2447+ *
2448+ * If @source_id has a count associated with it, that count will be
2449+ * decreased by one.
2450+ */
2451+void
2452+messaging_menu_app_remove_message (MessagingMenuApp *app,
2453+ MessagingMenuMessage *msg)
2454+{
2455+ /* take a ref of @msg here to make sure the pointer returned by
2456+ * _get_id() is valid for the duration of remove_message_by_id. */
2457+ g_object_ref (msg);
2458+ messaging_menu_app_remove_message_by_id (app, messaging_menu_message_get_id (msg));
2459+ g_object_unref (msg);
2460+}
2461+
2462+/**
2463+ * messaging_menu_app_remove_message_by_id:
2464+ * @app: a #MessagingMenuApp
2465+ * @id: the unique id of @msg
2466+ *
2467+ * Removes the message with the id @id from @app.
2468+ *
2469+ * If @source_id has a count associated with it, that count will be
2470+ * decreased by one.
2471+ */
2472+void
2473+messaging_menu_app_remove_message_by_id (MessagingMenuApp *app,
2474+ const gchar *id)
2475+{
2476+ g_return_if_fail (MESSAGING_MENU_IS_APP (app));
2477+ g_return_if_fail (id != NULL);
2478+
2479+ if (messaging_menu_app_remove_message_internal (app, id))
2480+ indicator_messages_application_emit_message_removed (app->app_interface, id);
2481+>>>>>>> MERGE-SOURCE
2482 }
2483
2484=== renamed file 'libmessaging-menu/messaging-menu.h' => 'libmessaging-menu/messaging-menu-app.h'
2485--- libmessaging-menu/messaging-menu.h 2012-08-31 17:19:21 +0000
2486+++ libmessaging-menu/messaging-menu-app.h 2013-07-12 19:50:34 +0000
2487@@ -17,10 +17,11 @@
2488 * Lars Uebernickel <lars.uebernickel@canonical.com>
2489 */
2490
2491-#ifndef __messaging_menu_h__
2492-#define __messaging_menu_h__
2493+#ifndef __messaging_menu_app_h__
2494+#define __messaging_menu_app_h__
2495
2496 #include <gio/gio.h>
2497+#include "messaging-menu-message.h"
2498
2499 G_BEGIN_DECLS
2500
2501@@ -143,6 +144,20 @@
2502 void messaging_menu_app_remove_attention (MessagingMenuApp *app,
2503 const gchar *source_id);
2504
2505+void messaging_menu_app_append_message (MessagingMenuApp *app,
2506+ MessagingMenuMessage *msg,
2507+ const gchar *source_id,
2508+ gboolean notify);
2509+
2510+MessagingMenuMessage * messaging_menu_app_get_message (MessagingMenuApp *app,
2511+ const gchar *id);
2512+
2513+void messaging_menu_app_remove_message (MessagingMenuApp *app,
2514+ MessagingMenuMessage *msg);
2515+
2516+void messaging_menu_app_remove_message_by_id (MessagingMenuApp *app,
2517+ const gchar *id);
2518+
2519 G_END_DECLS
2520
2521 #endif
2522
2523=== added file 'libmessaging-menu/messaging-menu-message.c'
2524--- libmessaging-menu/messaging-menu-message.c 1970-01-01 00:00:00 +0000
2525+++ libmessaging-menu/messaging-menu-message.c 2013-07-12 19:50:34 +0000
2526@@ -0,0 +1,547 @@
2527+/*
2528+ * Copyright 2012 Canonical Ltd.
2529+ *
2530+ * This program is free software: you can redistribute it and/or modify it
2531+ * under the terms of the GNU General Public License version 3, as
2532+ * published by the Free Software Foundation.
2533+ *
2534+ * This program is distributed in the hope that it will be useful, but
2535+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2536+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2537+ * PURPOSE. See the GNU General Public License for more details.
2538+ *
2539+ * You should have received a copy of the GNU General Public License along
2540+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2541+ *
2542+ * Authors:
2543+ * Lars Uebernickel <lars.uebernickel@canonical.com>
2544+ */
2545+
2546+#include "messaging-menu-message.h"
2547+
2548+typedef GObjectClass MessagingMenuMessageClass;
2549+
2550+struct _MessagingMenuMessage
2551+{
2552+ GObject parent;
2553+
2554+ gchar *id;
2555+ GIcon *icon;
2556+ gchar *title;
2557+ gchar *subtitle;
2558+ gchar *body;
2559+ gint64 time;
2560+ gboolean draws_attention;
2561+
2562+ GSList *actions;
2563+};
2564+
2565+G_DEFINE_TYPE (MessagingMenuMessage, messaging_menu_message, G_TYPE_OBJECT);
2566+
2567+enum
2568+{
2569+ PROP_0,
2570+ PROP_ID,
2571+ PROP_ICON,
2572+ PROP_TITLE,
2573+ PROP_SUBTITLE,
2574+ PROP_BODY,
2575+ PROP_TIME,
2576+ PROP_DRAWS_ATTENTION,
2577+ NUM_PROPERTIES
2578+};
2579+
2580+static GParamSpec *properties[NUM_PROPERTIES];
2581+
2582+typedef struct
2583+{
2584+ gchar *id;
2585+ gchar *label;
2586+ GVariantType *parameter_type;
2587+ GVariant *parameter_hint;
2588+} Action;
2589+
2590+static void
2591+action_free (gpointer data)
2592+{
2593+ Action *action = data;
2594+
2595+ g_free (action->id);
2596+ g_free (action->label);
2597+
2598+ if (action->parameter_type)
2599+ g_variant_type_free (action->parameter_type);
2600+
2601+ if (action->parameter_hint)
2602+ g_variant_unref (action->parameter_hint);
2603+
2604+ g_slice_free (Action, action);
2605+}
2606+
2607+static void
2608+messaging_menu_message_dispose (GObject *object)
2609+{
2610+ MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
2611+
2612+ g_clear_object (&msg->icon);
2613+
2614+ G_OBJECT_CLASS (messaging_menu_message_parent_class)->dispose (object);
2615+}
2616+
2617+static void
2618+messaging_menu_message_finalize (GObject *object)
2619+{
2620+ MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
2621+
2622+ g_free (msg->id);
2623+ g_free (msg->title);
2624+ g_free (msg->subtitle);
2625+ g_free (msg->body);
2626+
2627+ g_slist_free_full (msg->actions, action_free);
2628+ msg->actions = NULL;
2629+
2630+ G_OBJECT_CLASS (messaging_menu_message_parent_class)->finalize (object);
2631+}
2632+
2633+static void
2634+messaging_menu_message_get_property (GObject *object,
2635+ guint property_id,
2636+ GValue *value,
2637+ GParamSpec *pspec)
2638+{
2639+ MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
2640+
2641+ switch (property_id)
2642+ {
2643+ case PROP_ID:
2644+ g_value_set_string (value, msg->id);
2645+ break;
2646+
2647+ case PROP_ICON:
2648+ g_value_set_object (value, msg->icon);
2649+ break;
2650+
2651+ case PROP_TITLE:
2652+ g_value_set_string (value, msg->title);
2653+ break;
2654+
2655+ case PROP_SUBTITLE:
2656+ g_value_set_string (value, msg->subtitle);
2657+ break;
2658+
2659+ case PROP_BODY:
2660+ g_value_set_string (value, msg->body);
2661+
2662+ case PROP_TIME:
2663+ g_value_set_int64 (value, msg->time);
2664+ break;
2665+
2666+ case PROP_DRAWS_ATTENTION:
2667+ g_value_set_boolean (value, msg->draws_attention);
2668+ break;
2669+
2670+ default:
2671+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2672+ }
2673+}
2674+
2675+static void
2676+messaging_menu_message_set_property (GObject *object,
2677+ guint property_id,
2678+ const GValue *value,
2679+ GParamSpec *pspec)
2680+{
2681+ MessagingMenuMessage *msg = MESSAGING_MENU_MESSAGE (object);
2682+
2683+ switch (property_id)
2684+ {
2685+ case PROP_ID:
2686+ msg->id = g_value_dup_string (value);
2687+ break;
2688+
2689+ case PROP_ICON:
2690+ msg->icon = g_value_dup_object (value);
2691+ break;
2692+
2693+ case PROP_TITLE:
2694+ msg->title = g_value_dup_string (value);
2695+ break;
2696+
2697+ case PROP_SUBTITLE:
2698+ msg->subtitle = g_value_dup_string (value);
2699+ break;
2700+
2701+ case PROP_BODY:
2702+ msg->body = g_value_dup_string (value);
2703+
2704+ case PROP_TIME:
2705+ msg->time = g_value_get_int64 (value);
2706+ break;
2707+
2708+ case PROP_DRAWS_ATTENTION:
2709+ messaging_menu_message_set_draws_attention (msg, g_value_get_boolean (value));
2710+ break;
2711+
2712+ default:
2713+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2714+ }
2715+}
2716+
2717+static void
2718+messaging_menu_message_class_init (MessagingMenuMessageClass *klass)
2719+{
2720+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2721+
2722+ object_class->dispose = messaging_menu_message_dispose;
2723+ object_class->finalize = messaging_menu_message_finalize;
2724+ object_class->get_property = messaging_menu_message_get_property;
2725+ object_class->set_property = messaging_menu_message_set_property;
2726+
2727+ properties[PROP_ID] = g_param_spec_string ("id", "Id",
2728+ "Unique id of the message",
2729+ NULL,
2730+ G_PARAM_CONSTRUCT_ONLY |
2731+ G_PARAM_READWRITE |
2732+ G_PARAM_STATIC_STRINGS);
2733+
2734+ properties[PROP_ICON] = g_param_spec_object ("icon", "Icon",
2735+ "Icon of the message",
2736+ G_TYPE_ICON,
2737+ G_PARAM_CONSTRUCT_ONLY |
2738+ G_PARAM_READWRITE |
2739+ G_PARAM_STATIC_STRINGS);
2740+
2741+ properties[PROP_TITLE] = g_param_spec_string ("title", "Title",
2742+ "Title of the message",
2743+ NULL,
2744+ G_PARAM_CONSTRUCT_ONLY |
2745+ G_PARAM_READWRITE |
2746+ G_PARAM_STATIC_STRINGS);
2747+
2748+ properties[PROP_SUBTITLE] = g_param_spec_string ("subtitle", "Subtitle",
2749+ "Subtitle of the message",
2750+ NULL,
2751+ G_PARAM_CONSTRUCT_ONLY |
2752+ G_PARAM_READWRITE |
2753+ G_PARAM_STATIC_STRINGS);
2754+
2755+ properties[PROP_BODY] = g_param_spec_string ("body", "Body",
2756+ "First lines of the body of the message",
2757+ NULL,
2758+ G_PARAM_CONSTRUCT_ONLY |
2759+ G_PARAM_READWRITE |
2760+ G_PARAM_STATIC_STRINGS);
2761+
2762+ properties[PROP_TIME] = g_param_spec_int64 ("time", "Time",
2763+ "Time the message was sent, in microseconds", 0, G_MAXINT64, 0,
2764+ G_PARAM_CONSTRUCT_ONLY |
2765+ G_PARAM_READWRITE |
2766+ G_PARAM_STATIC_STRINGS);
2767+
2768+ properties[PROP_DRAWS_ATTENTION] = g_param_spec_boolean ("draws-attention", "Draws attention",
2769+ "Whether the message should draw attention",
2770+ FALSE,
2771+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
2772+
2773+ g_object_class_install_properties (klass, NUM_PROPERTIES, properties);
2774+
2775+ /**
2776+ * MessagingMenuMessage::activate:
2777+ * @msg: the #MessagingMenuMessage
2778+ * @action: (allow-none): the id of activated action, or %NULL
2779+ * @parameter: (allow-none): activation parameter, or %NULL
2780+ *
2781+ * Emitted when the user has activated the message. The message is
2782+ * immediately removed from the application's menu, handlers of this
2783+ * signal do not need to call messaging_menu_app_remove_message().
2784+ */
2785+ g_signal_new ("activate",
2786+ MESSAGING_MENU_TYPE_MESSAGE,
2787+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
2788+ 0,
2789+ NULL, NULL,
2790+ g_cclosure_marshal_generic,
2791+ G_TYPE_NONE, 2,
2792+ G_TYPE_STRING,
2793+ G_TYPE_VARIANT);
2794+}
2795+
2796+static void
2797+messaging_menu_message_init (MessagingMenuMessage *self)
2798+{
2799+}
2800+
2801+/**
2802+ * messaging_menu_message_new:
2803+ * @id: unique id of the message
2804+ * @icon: (transfer full) (allow-none): a #GIcon representing the message
2805+ * @title: the title of the message
2806+ * @subtitle: (allow-none): the subtitle of the message
2807+ * @body: (allow-none): the message body
2808+ * @time: the time the message was received
2809+ *
2810+ * Creates a new #MessagingMenuMessage.
2811+ *
2812+ * Returns: (transfer full): a new #MessagingMenuMessage
2813+ */
2814+MessagingMenuMessage *
2815+messaging_menu_message_new (const gchar *id,
2816+ GIcon *icon,
2817+ const gchar *title,
2818+ const gchar *subtitle,
2819+ const gchar *body,
2820+ gint64 time)
2821+{
2822+ g_return_val_if_fail (id != NULL, NULL);
2823+ g_return_val_if_fail (title != NULL, NULL);
2824+
2825+ return g_object_new (MESSAGING_MENU_TYPE_MESSAGE,
2826+ "id", id,
2827+ "icon", icon,
2828+ "title", title,
2829+ "subtitle", subtitle,
2830+ "body", body,
2831+ "time", time,
2832+ NULL);
2833+}
2834+
2835+/**
2836+ * messaging_menu_message_get_id:
2837+ * @msg: a #MessagingMenuMessage
2838+ *
2839+ * Returns: the unique id of @msg
2840+ */
2841+const gchar *
2842+messaging_menu_message_get_id (MessagingMenuMessage *msg)
2843+{
2844+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
2845+
2846+ return msg->id;
2847+}
2848+
2849+/**
2850+ * messaging_menu_message_get_icon:
2851+ * @msg: a #MessagingMenuMessage
2852+ *
2853+ * Returns: (transfer none): the icon of @msg
2854+ */
2855+GIcon *
2856+messaging_menu_message_get_icon (MessagingMenuMessage *msg)
2857+{
2858+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
2859+
2860+ return msg->icon;
2861+}
2862+
2863+/**
2864+ * messaging_menu_message_get_title:
2865+ * @msg: a #MessagingMenuMessage
2866+ *
2867+ * Returns: the title of @msg
2868+ */
2869+const gchar *
2870+messaging_menu_message_get_title (MessagingMenuMessage *msg)
2871+{
2872+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
2873+
2874+ return msg->title;
2875+}
2876+
2877+/**
2878+ * messaging_menu_message_get_subtitle:
2879+ * @msg: a #MessagingMenuMessage
2880+ *
2881+ * Returns: the subtitle of @msg
2882+ */
2883+const gchar *
2884+messaging_menu_message_get_subtitle (MessagingMenuMessage *msg)
2885+{
2886+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
2887+
2888+ return msg->subtitle;
2889+}
2890+
2891+/**
2892+ * messaging_menu_message_get_body:
2893+ * @msg: a #MessagingMenuMessage
2894+ *
2895+ * Returns: the body of @msg
2896+ */
2897+const gchar *
2898+messaging_menu_message_get_body (MessagingMenuMessage *msg)
2899+{
2900+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
2901+
2902+ return msg->body;
2903+}
2904+
2905+/**
2906+ * messaging_menu_message_get_time:
2907+ * @msg: a #MessagingMenuMessage
2908+ *
2909+ * Returns: the time at which @msg was received
2910+ */
2911+gint64
2912+messaging_menu_message_get_time (MessagingMenuMessage *msg)
2913+{
2914+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), 0);
2915+
2916+ return msg->time;
2917+}
2918+
2919+/**
2920+ * messaging_menu_message_get_draws_attention:
2921+ * @msg: a #MessagingMenuMessage
2922+ *
2923+ * Returns: whether @msg is drawing attention
2924+ */
2925+gboolean
2926+messaging_menu_message_get_draws_attention (MessagingMenuMessage *msg)
2927+{
2928+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), FALSE);
2929+
2930+ return msg->draws_attention;
2931+}
2932+
2933+/**
2934+ * messaging_menu_message_set_draws_attention:
2935+ * @msg: a #MessagingMenuMessage
2936+ * @draws_attention: whether @msg should draw attention
2937+ *
2938+ * Sets whether @msg is drawing attention.
2939+ */
2940+void
2941+messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
2942+ gboolean draws_attention)
2943+{
2944+ g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
2945+
2946+ msg->draws_attention = draws_attention;
2947+ g_object_notify_by_pspec (G_OBJECT (msg), properties[PROP_DRAWS_ATTENTION]);
2948+}
2949+
2950+/**
2951+ * messaging_menu_message_add_action:
2952+ * @msg: a #MessagingMenuMessage
2953+ * @id: unique id of the action
2954+ * @label: (allow-none): label of the action
2955+ * @parameter_type: (allow-none): a #GVariantType
2956+ * @parameter_hint: (allow-none): a #GVariant suggesting a valid range
2957+ * for parameters
2958+ *
2959+ * Adds an action with @id and @label to @message. Actions are an
2960+ * alternative way for users to activate a message. Note that messages
2961+ * can still be activated without an action.
2962+ *
2963+ * If @parameter_type is non-%NULL, the action is able to receive user
2964+ * input in addition to simply activating the action. Currently, only
2965+ * string parameters are supported.
2966+ *
2967+ * A list of predefined parameters can be supplied as a #GVariant array
2968+ * of @parameter_type in @parameter_hint. If @parameter_hint is
2969+ * floating, it will be consumed.
2970+ *
2971+ * It is recommended to add at most two actions to a message.
2972+ */
2973+void
2974+messaging_menu_message_add_action (MessagingMenuMessage *msg,
2975+ const gchar *id,
2976+ const gchar *label,
2977+ const GVariantType *parameter_type,
2978+ GVariant *parameter_hint)
2979+{
2980+ Action *action;
2981+
2982+ g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
2983+ g_return_if_fail (id != NULL);
2984+
2985+ action = g_slice_new (Action);
2986+ action->id = g_strdup (id);
2987+ action->label = g_strdup (label);
2988+ action->parameter_type = parameter_type ? g_variant_type_copy (parameter_type) : NULL;
2989+ action->parameter_hint = parameter_hint ? g_variant_ref_sink (parameter_hint) : NULL;
2990+
2991+ msg->actions = g_slist_append (msg->actions, action);
2992+}
2993+
2994+static GVariant *
2995+action_to_variant (Action *action)
2996+{
2997+ GVariantBuilder builder;
2998+
2999+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
3000+
3001+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (action->id));
3002+
3003+ if (action->label)
3004+ g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (action->label));
3005+
3006+ if (action->parameter_type)
3007+ {
3008+ gchar *type = g_variant_type_dup_string (action->parameter_type);
3009+ g_variant_builder_add (&builder, "{sv}", "parameter-type", g_variant_new_signature (type));
3010+ g_free (type);
3011+ }
3012+
3013+ if (action->parameter_hint)
3014+ g_variant_builder_add (&builder, "{sv}", "parameter-hint", action->parameter_hint);
3015+
3016+ return g_variant_builder_end (&builder);
3017+}
3018+
3019+/*<internal>
3020+ * _messaging_menu_message_to_variant:
3021+ * @msg: a #MessagingMenuMessage
3022+ *
3023+ * Serializes @msg to a #GVariant of the form (sssssxaa{sv}b):
3024+ *
3025+ * id
3026+ * icon
3027+ * title
3028+ * subtitle
3029+ * body
3030+ * time
3031+ * array of action dictionaries
3032+ * draws_attention
3033+ *
3034+ * Returns: a new floating #GVariant instance
3035+ */
3036+GVariant *
3037+_messaging_menu_message_to_variant (MessagingMenuMessage *msg)
3038+{
3039+ GVariantBuilder builder;
3040+ GSList *it;
3041+
3042+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
3043+
3044+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sssssxaa{sv}b)"));
3045+
3046+ g_variant_builder_add (&builder, "s", msg->id);
3047+
3048+ if (msg->icon)
3049+ {
3050+ gchar *iconstr;
3051+
3052+ iconstr = g_icon_to_string (msg->icon);
3053+ g_variant_builder_add (&builder, "s", iconstr);
3054+
3055+ g_free (iconstr);
3056+ }
3057+ else
3058+ g_variant_builder_add (&builder, "s", "");
3059+
3060+ g_variant_builder_add (&builder, "s", msg->title ? msg->title : "");
3061+ g_variant_builder_add (&builder, "s", msg->subtitle ? msg->subtitle : "");
3062+ g_variant_builder_add (&builder, "s", msg->body ? msg->body : "");
3063+ g_variant_builder_add (&builder, "x", msg->time);
3064+
3065+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{sv}"));
3066+ for (it = msg->actions; it; it = it->next)
3067+ g_variant_builder_add_value (&builder, action_to_variant (it->data));
3068+ g_variant_builder_close (&builder);
3069+
3070+ g_variant_builder_add (&builder, "b", msg->draws_attention);
3071+
3072+ return g_variant_builder_end (&builder);
3073+}
3074
3075=== added file 'libmessaging-menu/messaging-menu-message.h'
3076--- libmessaging-menu/messaging-menu-message.h 1970-01-01 00:00:00 +0000
3077+++ libmessaging-menu/messaging-menu-message.h 2013-07-12 19:50:34 +0000
3078@@ -0,0 +1,70 @@
3079+/*
3080+ * Copyright 2012 Canonical Ltd.
3081+ *
3082+ * This program is free software: you can redistribute it and/or modify it
3083+ * under the terms of the GNU General Public License version 3, as
3084+ * published by the Free Software Foundation.
3085+ *
3086+ * This program is distributed in the hope that it will be useful, but
3087+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3088+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3089+ * PURPOSE. See the GNU General Public License for more details.
3090+ *
3091+ * You should have received a copy of the GNU General Public License along
3092+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3093+ *
3094+ * Authors:
3095+ * Lars Uebernickel <lars.uebernickel@canonical.com>
3096+ */
3097+
3098+#ifndef __messaging_menu_message_h__
3099+#define __messaging_menu_message_h__
3100+
3101+#include <gio/gio.h>
3102+
3103+G_BEGIN_DECLS
3104+
3105+#define MESSAGING_MENU_TYPE_MESSAGE (messaging_menu_message_get_type ())
3106+#define MESSAGING_MENU_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessage))
3107+#define MESSAGING_MENU_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessageClass))
3108+#define MESSAGING_MENU_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MESSAGING_MENU_TYPE_MESSAGE))
3109+#define MESSAGING_MENU_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MESSAGING_MENU_TYPE_MESSAGE))
3110+#define MESSAGING_MENU_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MESSAGING_MENU_TYPE_MESSAGE, MessagingMenuMessageClass))
3111+
3112+typedef struct _MessagingMenuMessage MessagingMenuMessage;
3113+
3114+GType messaging_menu_message_get_type (void) G_GNUC_CONST;
3115+
3116+MessagingMenuMessage * messaging_menu_message_new (const gchar *id,
3117+ GIcon *icon,
3118+ const gchar *title,
3119+ const gchar *subtitle,
3120+ const gchar *body,
3121+ gint64 time);
3122+
3123+const gchar * messaging_menu_message_get_id (MessagingMenuMessage *msg);
3124+
3125+GIcon * messaging_menu_message_get_icon (MessagingMenuMessage *msg);
3126+
3127+const gchar * messaging_menu_message_get_title (MessagingMenuMessage *msg);
3128+
3129+const gchar * messaging_menu_message_get_subtitle (MessagingMenuMessage *msg);
3130+
3131+const gchar * messaging_menu_message_get_body (MessagingMenuMessage *msg);
3132+
3133+gint64 messaging_menu_message_get_time (MessagingMenuMessage *msg);
3134+
3135+gboolean messaging_menu_message_get_draws_attention (MessagingMenuMessage *msg);
3136+
3137+void messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
3138+ gboolean draws_attention);
3139+
3140+void messaging_menu_message_add_action (MessagingMenuMessage *msg,
3141+ const gchar *id,
3142+ const gchar *label,
3143+ const GVariantType *parameter_type,
3144+ GVariant *parameter_hint);
3145+
3146+G_END_DECLS
3147+
3148+#endif
3149
3150=== added file 'libmessaging-menu/messaging-menu.h'
3151--- libmessaging-menu/messaging-menu.h 1970-01-01 00:00:00 +0000
3152+++ libmessaging-menu/messaging-menu.h 2013-07-12 19:50:34 +0000
3153@@ -0,0 +1,25 @@
3154+/*
3155+ * Copyright 2012 Canonical Ltd.
3156+ *
3157+ * This program is free software: you can redistribute it and/or modify it
3158+ * under the terms of the GNU General Public License version 3, as
3159+ * published by the Free Software Foundation.
3160+ *
3161+ * This program is distributed in the hope that it will be useful, but
3162+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3163+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3164+ * PURPOSE. See the GNU General Public License for more details.
3165+ *
3166+ * You should have received a copy of the GNU General Public License along
3167+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3168+ *
3169+ * Authors:
3170+ * Lars Uebernickel <lars.uebernickel@canonical.com>
3171+ */
3172+
3173+#ifndef __messaging_menu_h__
3174+#define __messaging_menu_h__
3175+
3176+#include "messaging-menu-app.h"
3177+
3178+#endif
3179
3180=== modified file 'src/Makefile.am'
3181--- src/Makefile.am 2012-09-03 13:37:23 +0000
3182+++ src/Makefile.am 2013-07-12 19:50:34 +0000
3183@@ -1,8 +1,5 @@
3184
3185-BUILT_SOURCES =
3186 EXTRA_DIST =
3187-CLEANFILES =
3188-DISTCLEANFILES =
3189
3190 libexec_PROGRAMS = indicator-messages-service
3191
3192@@ -23,19 +20,20 @@
3193 im-source-menu-item.h \
3194 ido-detail-label.c \
3195 ido-detail-label.h \
3196- indicator-messages-service.c \
3197- indicator-messages-service.h
3198 dbus-data.h
3199 libmessaging_la_CFLAGS = \
3200 $(APPLET_CFLAGS) \
3201 $(COVERAGE_CFLAGS) \
3202+ -I$(top_builddir)/common \
3203 -Wall \
3204 -Wl,-Bsymbolic-functions \
3205 -Wl,-z,defs \
3206 -Wl,--as-needed \
3207 -Werror \
3208 -DG_LOG_DOMAIN=\"Indicator-Messages\"
3209-libmessaging_la_LIBADD = $(APPLET_LIBS) -lm
3210+libmessaging_la_LIBADD = \
3211+ $(top_builddir)/common/libmessaging-common.la \
3212+ $(APPLET_LIBS) -lm
3213 libmessaging_la_LDFLAGS = \
3214 $(COVERAGE_LDFLAGS) \
3215 -module -avoid-version
3216@@ -46,8 +44,6 @@
3217
3218 indicator_messages_service_SOURCES = \
3219 messages-service.c \
3220- indicator-messages-service.c \
3221- indicator-messages-service.h \
3222 app-section.c \
3223 app-section.h \
3224 dbus-data.h \
3225@@ -56,11 +52,16 @@
3226 gsettingsstrv.c \
3227 gsettingsstrv.h \
3228 gmenuutils.c \
3229- gmenuutils.h
3230+ gmenuutils.h \
3231+ im-phone-menu.c \
3232+ im-phone-menu.h \
3233+ im-application-list.c \
3234+ im-application-list.h
3235
3236 indicator_messages_service_CFLAGS = \
3237 $(APPLET_CFLAGS) \
3238 $(COVERAGE_CFLAGS) \
3239+ -I$(top_builddir)/common \
3240 -Wall \
3241 -Wl,-Bsymbolic-functions \
3242 -Wl,-z,defs \
3243@@ -69,26 +70,11 @@
3244 -DG_LOG_DOMAIN=\"Indicator-Messages\"
3245
3246 indicator_messages_service_LDADD = \
3247+ $(top_builddir)/common/libmessaging-common.la \
3248 $(APPLET_LIBS)
3249
3250 indicator_messages_service_LDFLAGS = \
3251 $(COVERAGE_LDFLAGS)
3252
3253-indicator-messages-service.c: $(top_srcdir)/src/messages-service.xml
3254- $(AM_V_GEN) gdbus-codegen \
3255- --interface-prefix com.canonical.indicator.messages. \
3256- --generate-c-code indicator-messages-service \
3257- --c-namespace IndicatorMessages \
3258- $^
3259-indicator-messages-service.h: indicator-messages-service.c
3260-
3261-BUILT_SOURCES += \
3262- indicator-messages-service.c \
3263- indicator-messages-service.h
3264-
3265 EXTRA_DIST += \
3266 messages-service.xml
3267-
3268-CLEANFILES += \
3269- $(BUILT_SOURCES)
3270-
3271
3272=== modified file 'src/app-section.c'
3273--- src/app-section.c 2013-04-22 15:26:51 +0000
3274+++ src/app-section.c 2013-07-12 19:50:34 +0000
3275@@ -34,6 +34,7 @@
3276 #include "dbus-data.h"
3277 #include "gmenuutils.h"
3278 #include "gactionmuxer.h"
3279+#include "indicator-messages-application.h"
3280
3281 struct _AppSectionPrivate
3282 {
3283@@ -42,11 +43,14 @@
3284
3285 IndicatorDesktopShortcuts * ids;
3286
3287+ GCancellable *app_proxy_cancellable;
3288+ IndicatorMessagesApplication *app_proxy;
3289+
3290 GMenu *menu;
3291- GMenuModel *source_menu;
3292+ GMenu *source_menu;
3293
3294 GSimpleActionGroup *static_shortcuts;
3295- GActionGroup *source_actions;
3296+ GSimpleActionGroup *source_actions;
3297 GActionMuxer *muxer;
3298
3299 gboolean draws_attention;
3300@@ -90,19 +94,6 @@
3301 gpointer user_data);
3302 static void app_section_set_app_info (AppSection *self,
3303 GDesktopAppInfo *appinfo);
3304-static gboolean any_action_draws_attention (GActionGroup *group,
3305- const gchar *ignored_action);
3306-static void action_added (GActionGroup *group,
3307- const gchar *action_name,
3308- gpointer user_data);
3309-static void action_state_changed (GActionGroup *group,
3310- const gchar *action_name,
3311- GVariant *value,
3312- gpointer user_data);
3313-static void action_removed (GActionGroup *group,
3314- const gchar *action_name,
3315- gpointer user_data);
3316-static gboolean action_draws_attention (GVariant *state);
3317 static void desktop_file_changed_cb (GFileMonitor *monitor,
3318 GFile *file,
3319 GFile *other_file,
3320@@ -170,6 +161,7 @@
3321 app_section_init (AppSection *self)
3322 {
3323 AppSectionPrivate *priv;
3324+ GMenuItem *item;
3325
3326 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
3327 APP_SECTION_TYPE,
3328@@ -179,10 +171,19 @@
3329 priv->appinfo = NULL;
3330
3331 priv->menu = g_menu_new ();
3332+
3333+ priv->source_menu = g_menu_new ();
3334+ item = g_menu_item_new_section (NULL, G_MENU_MODEL (priv->source_menu));
3335+ g_menu_item_set_attribute (item, "action-namespace", "s", "source");
3336+ g_menu_append_item (priv->menu, item);
3337+ g_object_unref (item);
3338+
3339 priv->static_shortcuts = g_simple_action_group_new ();
3340+ priv->source_actions = g_simple_action_group_new ();
3341
3342 priv->muxer = g_action_muxer_new ();
3343 g_action_muxer_insert (priv->muxer, NULL, G_ACTION_GROUP (priv->static_shortcuts));
3344+ g_action_muxer_insert (priv->muxer, "source", G_ACTION_GROUP (priv->source_actions));
3345
3346 priv->draws_attention = FALSE;
3347
3348@@ -249,32 +250,30 @@
3349 AppSection * self = APP_SECTION(object);
3350 AppSectionPrivate * priv = self->priv;
3351
3352+ if (priv->app_proxy_cancellable) {
3353+ g_cancellable_cancel (priv->app_proxy_cancellable);
3354+ g_clear_object (&priv->app_proxy_cancellable);
3355+ }
3356+
3357 if (priv->desktop_file_monitor) {
3358 g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
3359 g_clear_object (&priv->desktop_file_monitor);
3360 }
3361
3362+ g_clear_object (&priv->app_proxy);
3363+
3364 g_clear_object (&priv->menu);
3365+ g_clear_object (&priv->source_menu);
3366 g_clear_object (&priv->static_shortcuts);
3367+ g_clear_object (&priv->source_actions);
3368
3369 if (priv->name_watch_id) {
3370 g_bus_unwatch_name (priv->name_watch_id);
3371 priv->name_watch_id = 0;
3372 }
3373
3374- if (priv->source_actions) {
3375- g_action_muxer_remove (priv->muxer, "source");
3376- g_object_disconnect (priv->source_actions,
3377- "any_signal::action-added", action_added, self,
3378- "any_signal::action-state-changed", action_state_changed, self,
3379- "any_signal::action-removed", action_removed, self,
3380- NULL);
3381- g_clear_object (&priv->source_actions);
3382- }
3383-
3384 g_clear_object (&priv->muxer);
3385
3386- g_clear_object (&priv->source_menu);
3387 g_clear_object (&priv->ids);
3388 g_clear_object (&priv->appinfo);
3389
3390@@ -314,9 +313,13 @@
3391
3392 g_return_if_fail(priv->ids != NULL);
3393
3394+<<<<<<< TREE
3395 GAppLaunchContext *context = get_launch_context (g_variant_get_uint32 (param));
3396
3397 if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, context)) {
3398+=======
3399+ if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, NULL)) {
3400+>>>>>>> MERGE-SOURCE
3401 g_warning("Unable to execute nick '%s' for desktop file '%s'",
3402 nick, g_desktop_app_info_get_filename (priv->appinfo));
3403 }
3404@@ -445,6 +448,11 @@
3405 g_free(name);
3406 }
3407
3408+ item = g_menu_item_new_section (NULL, G_MENU_MODEL (priv->source_menu));
3409+ g_menu_item_set_attribute (item, "action-namespace", "s", "source");
3410+ g_menu_append_item (priv->menu, item);
3411+ g_object_unref (item);
3412+
3413 keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
3414 g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
3415
3416@@ -583,39 +591,8 @@
3417 void
3418 app_section_clear_draws_attention (AppSection *self)
3419 {
3420- AppSectionPrivate * priv = self->priv;
3421- gchar **action_names;
3422- gchar **it;
3423-
3424- if (priv->source_actions == NULL)
3425- return;
3426-
3427- action_names = g_action_group_list_actions (priv->source_actions);
3428-
3429- for (it = action_names; *it; it++) {
3430- GVariant *state;
3431-
3432- state = g_action_group_get_action_state (priv->source_actions, *it);
3433- if (!state)
3434- continue;
3435-
3436- /* clear draws-attention while preserving other state */
3437- if (action_draws_attention (state)) {
3438- guint32 count;
3439- gint64 time;
3440- const gchar *str;
3441- GVariant *new_state;
3442-
3443- g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL);
3444-
3445- new_state = g_variant_new ("(uxsb)", count, time, str, FALSE);
3446- g_action_group_change_action_state (priv->source_actions, *it, new_state);
3447- }
3448-
3449- g_variant_unref (state);
3450- }
3451-
3452- g_strfreev (action_names);
3453+ self->priv->draws_attention = FALSE;
3454+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3455 }
3456
3457 static void
3458@@ -628,6 +605,230 @@
3459 app_section_unset_object_path (self);
3460 }
3461
3462+static void
3463+update_draws_attention (AppSection *self)
3464+{
3465+ AppSectionPrivate *priv = self->priv;
3466+ gchar **actions;
3467+ gchar **it;
3468+ gboolean draws_attention = FALSE;
3469+
3470+ actions = g_action_group_list_actions (G_ACTION_GROUP (priv->source_actions));
3471+
3472+ for (it = actions; *it; it++) {
3473+ GVariant *state;
3474+
3475+ state = g_action_group_get_action_state (G_ACTION_GROUP (priv->source_actions), *it);
3476+ if (state) {
3477+ gboolean b;
3478+ g_variant_get (state, "(uxsb)", NULL, NULL, NULL, &b);
3479+ draws_attention = b || draws_attention;
3480+ g_variant_unref (state);
3481+ }
3482+
3483+ if (draws_attention)
3484+ break;
3485+ }
3486+
3487+ if (draws_attention != priv->draws_attention) {
3488+ priv->draws_attention = draws_attention;
3489+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3490+ }
3491+
3492+ g_strfreev (actions);
3493+}
3494+
3495+static void
3496+remove_source (AppSection *self,
3497+ const gchar *id)
3498+{
3499+ AppSectionPrivate *priv = self->priv;
3500+ guint n_items;
3501+ guint i;
3502+
3503+ n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->source_menu));
3504+ for (i = 0; i < n_items; i++) {
3505+ gchar *action;
3506+ gboolean found = FALSE;
3507+
3508+ if (g_menu_model_get_item_attribute (G_MENU_MODEL (priv->source_menu), i,
3509+ G_MENU_ATTRIBUTE_ACTION, "s", &action)) {
3510+ found = g_str_equal (action, id);
3511+ g_free (action);
3512+ }
3513+
3514+ if (found) {
3515+ g_menu_remove (priv->source_menu, i);
3516+ break;
3517+ }
3518+ }
3519+
3520+ g_simple_action_group_remove (priv->source_actions, id);
3521+ update_draws_attention (self);
3522+}
3523+
3524+static void
3525+source_action_activated (GSimpleAction *action,
3526+ GVariant *parameter,
3527+ gpointer user_data)
3528+{
3529+ AppSection *self = APP_SECTION (user_data);
3530+ AppSectionPrivate *priv = APP_SECTION (user_data)->priv;
3531+
3532+ g_return_if_fail (priv->app_proxy != NULL);
3533+
3534+ indicator_messages_application_call_activate_source (priv->app_proxy,
3535+ g_action_get_name (G_ACTION (action)),
3536+ priv->app_proxy_cancellable,
3537+ NULL, NULL);
3538+
3539+ remove_source (self, g_action_get_name (G_ACTION (action)));
3540+}
3541+
3542+static void
3543+sources_listed (GObject *source_object,
3544+ GAsyncResult *result,
3545+ gpointer user_data)
3546+{
3547+ AppSection *self = user_data;
3548+ AppSectionPrivate *priv = self->priv;
3549+ GVariant *sources = NULL;
3550+ GError *error = NULL;
3551+ GVariantIter iter;
3552+ const gchar *id;
3553+ const gchar *label;
3554+ const gchar *iconstr;
3555+ guint32 count;
3556+ gint64 time;
3557+ const gchar *string;
3558+ gboolean draws_attention;
3559+
3560+ if (!indicator_messages_application_call_list_sources_finish (INDICATOR_MESSAGES_APPLICATION (source_object),
3561+ &sources, result, &error))
3562+ {
3563+ g_warning ("could not fetch the list of sources: %s", error->message);
3564+ g_error_free (error);
3565+ return;
3566+ }
3567+
3568+ g_menu_clear (priv->source_menu);
3569+ g_simple_action_group_clear (priv->source_actions);
3570+ priv->draws_attention = FALSE;
3571+
3572+ g_variant_iter_init (&iter, sources);
3573+ while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr,
3574+ &count, &time, &string, &draws_attention))
3575+ {
3576+ GVariant *state;
3577+ GSimpleAction *action;
3578+ GMenuItem *item;
3579+
3580+ state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
3581+ action = g_simple_action_new_stateful (id, NULL, state);
3582+ g_signal_connect (action, "activate", G_CALLBACK (source_action_activated), self);
3583+ g_simple_action_group_insert (priv->source_actions, G_ACTION (action));
3584+
3585+ item = g_menu_item_new (label, id);
3586+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "ImSourceMenuItem");
3587+ g_menu_append_item (priv->source_menu, item);
3588+
3589+ priv->draws_attention = priv->draws_attention || draws_attention;
3590+
3591+ g_object_unref (item);
3592+ g_object_unref (action);
3593+ }
3594+
3595+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3596+
3597+ g_variant_unref (sources);
3598+}
3599+
3600+static void
3601+source_added (IndicatorMessagesApplication *app,
3602+ const gchar *id,
3603+ const gchar *label,
3604+ const gchar *iconstr,
3605+ guint count,
3606+ gint64 time,
3607+ const gchar *string,
3608+ gboolean draws_attention,
3609+ gpointer user_data)
3610+{
3611+ AppSection *self = user_data;
3612+ AppSectionPrivate *priv = self->priv;
3613+ GVariant *state;
3614+ GSimpleAction *action;
3615+
3616+ /* TODO put label and icon into the action as well */
3617+
3618+ state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
3619+ action = g_simple_action_new_stateful (id, NULL, state);
3620+
3621+ g_simple_action_group_insert (priv->source_actions, G_ACTION (action));
3622+
3623+ if (draws_attention && !priv->draws_attention) {
3624+ priv->draws_attention = TRUE;
3625+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3626+ }
3627+
3628+ g_object_unref (action);
3629+}
3630+static void
3631+source_changed (IndicatorMessagesApplication *app,
3632+ const gchar *id,
3633+ const gchar *label,
3634+ const gchar *iconstr,
3635+ guint count,
3636+ gint64 time,
3637+ const gchar *string,
3638+ gboolean draws_attention,
3639+ gpointer user_data)
3640+{
3641+ AppSection *self = user_data;
3642+ AppSectionPrivate *priv = self->priv;
3643+ GVariant *state;
3644+
3645+ /* TODO put label and icon into the action as well */
3646+
3647+ state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
3648+ g_action_group_change_action_state (G_ACTION_GROUP (priv->source_actions), id, state);
3649+
3650+ update_draws_attention (self);
3651+}
3652+
3653+static void
3654+source_removed (IndicatorMessagesApplication *app,
3655+ const gchar *id,
3656+ gpointer user_data)
3657+{
3658+ AppSection *self = user_data;
3659+
3660+ remove_source (self, id);
3661+}
3662+
3663+static void
3664+app_proxy_created (GObject *source_object,
3665+ GAsyncResult *result,
3666+ gpointer user_data)
3667+{
3668+ AppSectionPrivate *priv = APP_SECTION (user_data)->priv;
3669+ GError *error = NULL;
3670+
3671+ priv->app_proxy = indicator_messages_application_proxy_new_finish (result, &error);
3672+ if (!priv->app_proxy) {
3673+ g_warning ("could not create application proxy: %s", error->message);
3674+ g_error_free (error);
3675+ return;
3676+ }
3677+
3678+ indicator_messages_application_call_list_sources (priv->app_proxy, priv->app_proxy_cancellable,
3679+ sources_listed, user_data);
3680+
3681+ g_signal_connect (priv->app_proxy, "source-added", G_CALLBACK (source_added), user_data);
3682+ g_signal_connect (priv->app_proxy, "source-changed", G_CALLBACK (source_changed), user_data);
3683+ g_signal_connect (priv->app_proxy, "source-removed", G_CALLBACK (source_removed), user_data);
3684+}
3685+
3686 /*
3687 * app_section_set_object_path:
3688 * @self: an #AppSection
3689@@ -646,27 +847,20 @@
3690 const gchar *object_path)
3691 {
3692 AppSectionPrivate *priv = self->priv;
3693- GMenuItem *item;
3694
3695 g_object_freeze_notify (G_OBJECT (self));
3696 app_section_unset_object_path (self);
3697
3698- priv->source_actions = G_ACTION_GROUP (g_dbus_action_group_get (bus, bus_name, object_path));
3699- g_action_muxer_insert (priv->muxer, "source", priv->source_actions);
3700-
3701- priv->draws_attention = any_action_draws_attention (priv->source_actions, NULL);
3702- g_object_connect (priv->source_actions,
3703- "signal::action-added", action_added, self,
3704- "signal::action-state-changed", action_state_changed, self,
3705- "signal::action-removed", action_removed, self,
3706- NULL);
3707-
3708- priv->source_menu = G_MENU_MODEL (g_dbus_menu_model_get (bus, bus_name, object_path));
3709-
3710- item = g_menu_item_new_section (NULL, priv->source_menu);
3711- g_menu_item_set_attribute (item, "action-namespace", "s", "source");
3712- g_menu_append_item (priv->menu, item);
3713- g_object_unref (item);
3714+ priv->app_proxy_cancellable = g_cancellable_new ();
3715+ indicator_messages_application_proxy_new (bus,
3716+ G_DBUS_PROXY_FLAGS_NONE,
3717+ bus_name,
3718+ object_path,
3719+ priv->app_proxy_cancellable,
3720+ app_proxy_created,
3721+ self);
3722+
3723+ priv->draws_attention = FALSE;
3724
3725 priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,
3726 NULL, application_vanished,
3727@@ -694,26 +888,19 @@
3728 {
3729 AppSectionPrivate *priv = self->priv;
3730
3731+ if (priv->app_proxy_cancellable) {
3732+ g_cancellable_cancel (priv->app_proxy_cancellable);
3733+ g_clear_object (&priv->app_proxy_cancellable);
3734+ }
3735+ g_clear_object (&priv->app_proxy);
3736+
3737 if (priv->name_watch_id) {
3738 g_bus_unwatch_name (priv->name_watch_id);
3739 priv->name_watch_id = 0;
3740 }
3741
3742- if (priv->source_actions) {
3743- g_object_disconnect (priv->source_actions,
3744- "any_signal::action-added", action_added, self,
3745- "any_signal::action-state-changed", action_state_changed, self,
3746- "any_signal::action-removed", action_removed, self,
3747- NULL);
3748- g_clear_object (&priv->source_actions);
3749- }
3750-
3751- if (priv->source_menu) {
3752- /* the last menu item points is linked to the app's menumodel */
3753- gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu));
3754- g_menu_remove (priv->menu, n_items -1);
3755- g_clear_object (&priv->source_menu);
3756- }
3757+ g_simple_action_group_clear (priv->source_actions);
3758+ g_menu_clear (priv->source_menu);
3759
3760 priv->draws_attention = FALSE;
3761 g_clear_pointer (&priv->chat_status, g_free);
3762@@ -727,85 +914,6 @@
3763 "launch", g_variant_new_boolean (FALSE));
3764 }
3765
3766-static gboolean
3767-action_draws_attention (GVariant *state)
3768-{
3769- gboolean attention;
3770-
3771- if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")))
3772- g_variant_get_child (state, 3, "b", &attention);
3773- else
3774- attention = FALSE;
3775-
3776- return attention;
3777-}
3778-
3779-static gboolean
3780-any_action_draws_attention (GActionGroup *group,
3781- const gchar *ignored_action)
3782-{
3783- gchar **actions;
3784- gchar **it;
3785- gboolean attention = FALSE;
3786-
3787- actions = g_action_group_list_actions (group);
3788-
3789- for (it = actions; *it && !attention; it++) {
3790- GVariant *state;
3791-
3792- if (ignored_action && g_str_equal (ignored_action, *it))
3793- continue;
3794-
3795- state = g_action_group_get_action_state (group, *it);
3796- if (state) {
3797- attention = action_draws_attention (state);
3798- g_variant_unref (state);
3799- }
3800- }
3801-
3802- g_strfreev (actions);
3803- return attention;
3804-}
3805-
3806-static void
3807-action_added (GActionGroup *group,
3808- const gchar *action_name,
3809- gpointer user_data)
3810-{
3811- AppSection *self = user_data;
3812- GVariant *state;
3813-
3814- state = g_action_group_get_action_state (group, action_name);
3815- if (state) {
3816- self->priv->draws_attention |= action_draws_attention (state);
3817- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3818- g_variant_unref (state);
3819- }
3820-}
3821-
3822-static void
3823-action_state_changed (GActionGroup *group,
3824- const gchar *action_name,
3825- GVariant *value,
3826- gpointer user_data)
3827-{
3828- AppSection *self = user_data;
3829-
3830- self->priv->draws_attention = any_action_draws_attention (group, NULL);
3831- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3832-}
3833-
3834-static void
3835-action_removed (GActionGroup *group,
3836- const gchar *action_name,
3837- gpointer user_data)
3838-{
3839- AppSection *self = user_data;
3840-
3841- self->priv->draws_attention = any_action_draws_attention (group, action_name);
3842- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
3843-}
3844-
3845 gboolean
3846 app_section_get_uses_chat_status (AppSection *self)
3847 {
3848
3849=== modified file 'src/dbus-data.h'
3850--- src/dbus-data.h 2012-08-21 09:40:47 +0000
3851+++ src/dbus-data.h 2013-07-12 19:50:34 +0000
3852@@ -1,9 +1,24 @@
3853+/*
3854+ * Copyright 2012-2013 Canonical Ltd.
3855+ *
3856+ * This program is free software: you can redistribute it and/or modify it
3857+ * under the terms of the GNU General Public License version 3, as published
3858+ * by the Free Software Foundation.
3859+ *
3860+ * This program is distributed in the hope that it will be useful, but
3861+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3862+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3863+ * PURPOSE. See the GNU General Public License for more details.
3864+ *
3865+ * You should have received a copy of the GNU General Public License along
3866+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3867+ */
3868
3869 #ifndef __DBUS_DATA_H__
3870 #define __DBUS_DATA_H__ 1
3871
3872 #define INDICATOR_MESSAGES_DBUS_NAME "com.canonical.indicator.messages"
3873-#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/canonical/indicator/messages/menu"
3874+#define INDICATOR_MESSAGES_DBUS_OBJECT "/com/canonical/indicator/messages"
3875
3876 #define INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT "/com/canonical/indicator/messages/service"
3877 #define INDICATOR_MESSAGES_DBUS_SERVICE_INTERFACE "com.canonical.indicator.messages.service"
3878
3879=== modified file 'src/gactionmuxer.c'
3880--- src/gactionmuxer.c 2012-06-04 21:43:56 +0000
3881+++ src/gactionmuxer.c 2013-07-12 19:50:34 +0000
3882@@ -483,3 +483,11 @@
3883 g_clear_object (&muxer->global_actions);
3884 }
3885
3886+GActionGroup *
3887+g_action_muxer_get_group (GActionMuxer *muxer,
3888+ const gchar *prefix)
3889+{
3890+ g_return_val_if_fail (G_IS_ACTION_MUXER (muxer), NULL);
3891+
3892+ return prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions;
3893+}
3894
3895=== modified file 'src/gactionmuxer.h'
3896--- src/gactionmuxer.h 2012-06-03 06:33:31 +0000
3897+++ src/gactionmuxer.h 2013-07-12 19:50:34 +0000
3898@@ -40,5 +40,8 @@
3899 void g_action_muxer_remove (GActionMuxer *muxer,
3900 const gchar *prefix);
3901
3902+GActionGroup * g_action_muxer_get_group (GActionMuxer *muxer,
3903+ const gchar *prefix);
3904+
3905 #endif
3906
3907
3908=== modified file 'src/ido-detail-label.c'
3909--- src/ido-detail-label.c 2013-05-29 13:55:39 +0000
3910+++ src/ido-detail-label.c 2013-07-12 19:50:34 +0000
3911@@ -138,6 +138,7 @@
3912 gtk_widget_get_font_metrics (GtkWidget *widget,
3913 PangoContext *context)
3914 {
3915+<<<<<<< TREE
3916 PangoFontDescription *font;
3917 PangoFontMetrics *metrics;
3918
3919@@ -151,6 +152,20 @@
3920
3921 pango_font_description_free (font);
3922 return metrics;
3923+=======
3924+ PangoFontMetrics *font_metrics;
3925+ PangoFontDescription *font;
3926+ GtkStyleContext *style;
3927+ style = gtk_widget_get_style_context (GTK_WIDGET (widget));
3928+ gtk_style_context_get (style, GTK_STATE_FLAG_NORMAL,
3929+ "font", &font, NULL);
3930+
3931+ font_metrics = pango_context_get_metrics (context,
3932+ font,
3933+ pango_context_get_language (context));
3934+ pango_font_description_free (font);
3935+ return font_metrics;
3936+>>>>>>> MERGE-SOURCE
3937 }
3938
3939 static gint
3940
3941=== added file 'src/im-application-list.c'
3942--- src/im-application-list.c 1970-01-01 00:00:00 +0000
3943+++ src/im-application-list.c 2013-07-12 19:50:34 +0000
3944@@ -0,0 +1,880 @@
3945+/*
3946+ * Copyright 2012 Canonical Ltd.
3947+ *
3948+ * This program is free software: you can redistribute it and/or modify it
3949+ * under the terms of the GNU General Public License version 3, as published
3950+ * by the Free Software Foundation.
3951+ *
3952+ * This program is distributed in the hope that it will be useful, but
3953+ * WITHOUT ANY WARRANTY; without even the implied warranties of
3954+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3955+ * PURPOSE. See the GNU General Public License for more details.
3956+ *
3957+ * You should have received a copy of the GNU General Public License along
3958+ * with this program. If not, see <http://www.gnu.org/licenses/>.
3959+ *
3960+ * Authors:
3961+ * Lars Uebernickel <lars.uebernickel@canonical.com>
3962+ */
3963+
3964+#include "im-application-list.h"
3965+
3966+#include "indicator-messages-application.h"
3967+#include "gactionmuxer.h"
3968+
3969+#include <gio/gdesktopappinfo.h>
3970+#include <string.h>
3971+
3972+typedef GObjectClass ImApplicationListClass;
3973+
3974+struct _ImApplicationList
3975+{
3976+ GObject parent;
3977+
3978+ GHashTable *applications;
3979+ GActionMuxer *muxer;
3980+};
3981+
3982+G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT);
3983+
3984+enum
3985+{
3986+ SOURCE_ADDED,
3987+ SOURCE_CHANGED,
3988+ SOURCE_REMOVED,
3989+ MESSAGE_ADDED,
3990+ MESSAGE_REMOVED,
3991+ APP_STOPPED,
3992+ REMOVE_ALL,
3993+ N_SIGNALS
3994+};
3995+
3996+static guint signals[N_SIGNALS];
3997+
3998+typedef struct
3999+{
4000+ ImApplicationList *list;
4001+ GDesktopAppInfo *info;
4002+ gchar *id;
4003+ IndicatorMessagesApplication *proxy;
4004+ GActionMuxer *actions;
4005+ GSimpleActionGroup *source_actions;
4006+ GSimpleActionGroup *message_actions;
4007+ GActionMuxer *message_sub_actions;
4008+ GCancellable *cancellable;
4009+} Application;
4010+
4011+static void
4012+application_free (gpointer data)
4013+{
4014+ Application *app = data;
4015+
4016+ if (!app)
4017+ return;
4018+
4019+ g_object_unref (app->info);
4020+ g_free (app->id);
4021+
4022+ if (app->cancellable)
4023+ {
4024+ g_cancellable_cancel (app->cancellable);
4025+ g_clear_object (&app->cancellable);
4026+ }
4027+
4028+ if (app->proxy)
4029+ g_object_unref (app->proxy);
4030+
4031+ if (app->actions)
4032+ {
4033+ g_object_unref (app->actions);
4034+ g_object_unref (app->source_actions);
4035+ g_object_unref (app->message_actions);
4036+ g_object_unref (app->message_sub_actions);
4037+ }
4038+
4039+ g_slice_free (Application, app);
4040+}
4041+
4042+static void
4043+im_application_list_source_removed (Application *app,
4044+ const gchar *id)
4045+{
4046+ g_simple_action_group_remove (app->source_actions, id);
4047+
4048+ g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id);
4049+}
4050+
4051+static void
4052+im_application_list_source_activated (GSimpleAction *action,
4053+ GVariant *parameter,
4054+ gpointer user_data)
4055+{
4056+ Application *app = user_data;
4057+ const gchar *source_id;
4058+
4059+ source_id = g_action_get_name (G_ACTION (action));
4060+
4061+ if (g_variant_get_boolean (parameter))
4062+ {
4063+ indicator_messages_application_call_activate_source (app->proxy,
4064+ source_id,
4065+ app->cancellable,
4066+ NULL, NULL);
4067+ }
4068+ else
4069+ {
4070+ const gchar *sources[] = { source_id, NULL };
4071+ const gchar *messages[] = { NULL };
4072+ indicator_messages_application_call_dismiss (app->proxy, sources, messages,
4073+ app->cancellable, NULL, NULL);
4074+ }
4075+
4076+ im_application_list_source_removed (app, source_id);
4077+}
4078+
4079+static guint
4080+g_action_group_get_n_actions (GActionGroup *group)
4081+{
4082+ guint len;
4083+ gchar **actions;
4084+
4085+ actions = g_action_group_list_actions (group);
4086+ len = g_strv_length (actions);
4087+
4088+ g_strfreev (actions);
4089+ return len;
4090+}
4091+
4092+static gboolean
4093+application_draws_attention (gpointer key,
4094+ gpointer value,
4095+ gpointer user_data)
4096+{
4097+ Application *app = value;
4098+
4099+ return (g_action_group_get_n_actions (G_ACTION_GROUP (app->source_actions)) +
4100+ g_action_group_get_n_actions (G_ACTION_GROUP (app->message_actions))) > 0;
4101+}
4102+
4103+static void
4104+im_application_list_update_draws_attention (ImApplicationList *list)
4105+{
4106+ const gchar *icon_name;
4107+ GVariant *state;
4108+ GActionGroup *main_actions;
4109+
4110+ if (g_hash_table_find (list->applications, application_draws_attention, NULL))
4111+ icon_name = "indicator-messages-new";
4112+ else
4113+ icon_name = "indicator-messages";
4114+
4115+ main_actions = g_action_muxer_get_group (list->muxer, NULL);
4116+ state = g_variant_new ("(sssb)", "", icon_name, "Messages", TRUE);
4117+ g_action_group_change_action_state (main_actions, "messages", state);
4118+}
4119+
4120+static void
4121+im_application_list_message_removed (Application *app,
4122+ const gchar *id)
4123+{
4124+ g_simple_action_group_remove (app->message_actions, id);
4125+ g_action_muxer_remove (app->message_sub_actions, id);
4126+
4127+ im_application_list_update_draws_attention (app->list);
4128+
4129+ g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id);
4130+}
4131+
4132+static void
4133+im_application_list_message_activated (GSimpleAction *action,
4134+ GVariant *parameter,
4135+ gpointer user_data)
4136+{
4137+ Application *app = user_data;
4138+ const gchar *message_id;
4139+
4140+ message_id = g_action_get_name (G_ACTION (action));
4141+
4142+ if (g_variant_get_boolean (parameter))
4143+ {
4144+ indicator_messages_application_call_activate_message (app->proxy,
4145+ message_id,
4146+ "",
4147+ g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0),
4148+ app->cancellable,
4149+ NULL, NULL);
4150+ }
4151+ else
4152+ {
4153+ const gchar *sources[] = { NULL };
4154+ const gchar *messages[] = { message_id, NULL };
4155+ indicator_messages_application_call_dismiss (app->proxy, sources, messages,
4156+ app->cancellable, NULL, NULL);
4157+ }
4158+
4159+ im_application_list_message_removed (app, message_id);
4160+}
4161+
4162+static void
4163+im_application_list_sub_message_activated (GSimpleAction *action,
4164+ GVariant *parameter,
4165+ gpointer user_data)
4166+{
4167+ Application *app = user_data;
4168+ const gchar *message_id;
4169+ const gchar *action_id;
4170+ GVariantBuilder builder;
4171+
4172+ message_id = g_object_get_data (G_OBJECT (action), "message");
4173+ action_id = g_action_get_name (G_ACTION (action));
4174+
4175+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
4176+ if (parameter)
4177+ g_variant_builder_add (&builder, "v", parameter);
4178+
4179+ indicator_messages_application_call_activate_message (app->proxy,
4180+ message_id,
4181+ action_id,
4182+ g_variant_builder_end (&builder),
4183+ app->cancellable,
4184+ NULL, NULL);
4185+
4186+ im_application_list_message_removed (app, message_id);
4187+}
4188+
4189+
4190+static void
4191+im_application_list_remove_all (GSimpleAction *action,
4192+ GVariant *parameter,
4193+ gpointer user_data)
4194+{
4195+ ImApplicationList *list = user_data;
4196+ GHashTableIter iter;
4197+ Application *app;
4198+
4199+ g_signal_emit (list, signals[REMOVE_ALL], 0);
4200+
4201+ g_hash_table_iter_init (&iter, list->applications);
4202+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app))
4203+ {
4204+ gchar **source_actions;
4205+ gchar **message_actions;
4206+ gchar **it;
4207+
4208+ source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions));
4209+ for (it = source_actions; *it; it++)
4210+ im_application_list_source_removed (app, *it);
4211+
4212+ message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions));
4213+ for (it = message_actions; *it; it++)
4214+ im_application_list_message_removed (app, *it);
4215+
4216+ indicator_messages_application_call_dismiss (app->proxy,
4217+ (const gchar * const *) source_actions,
4218+ (const gchar * const *) message_actions,
4219+ app->cancellable, NULL, NULL);
4220+
4221+ g_strfreev (source_actions);
4222+ g_strfreev (message_actions);
4223+ }
4224+}
4225+
4226+static void
4227+im_application_list_dispose (GObject *object)
4228+{
4229+ ImApplicationList *list = IM_APPLICATION_LIST (object);
4230+
4231+ g_clear_pointer (&list->applications, g_hash_table_unref);
4232+ g_clear_object (&list->muxer);
4233+
4234+ G_OBJECT_CLASS (im_application_list_parent_class)->dispose (object);
4235+}
4236+
4237+static void
4238+im_application_list_finalize (GObject *object)
4239+{
4240+ G_OBJECT_CLASS (im_application_list_parent_class)->finalize (object);
4241+}
4242+
4243+static void
4244+im_application_list_class_init (ImApplicationListClass *klass)
4245+{
4246+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
4247+
4248+ object_class->dispose = im_application_list_dispose;
4249+ object_class->finalize = im_application_list_finalize;
4250+
4251+ signals[SOURCE_ADDED] = g_signal_new ("source-added",
4252+ IM_TYPE_APPLICATION_LIST,
4253+ G_SIGNAL_RUN_FIRST,
4254+ 0,
4255+ NULL, NULL,
4256+ g_cclosure_marshal_generic,
4257+ G_TYPE_NONE,
4258+ 4,
4259+ G_TYPE_STRING,
4260+ G_TYPE_STRING,
4261+ G_TYPE_STRING,
4262+ G_TYPE_STRING);
4263+
4264+ signals[SOURCE_CHANGED] = g_signal_new ("source-changed",
4265+ IM_TYPE_APPLICATION_LIST,
4266+ G_SIGNAL_RUN_FIRST,
4267+ 0,
4268+ NULL, NULL,
4269+ g_cclosure_marshal_generic,
4270+ G_TYPE_NONE,
4271+ 4,
4272+ G_TYPE_STRING,
4273+ G_TYPE_STRING,
4274+ G_TYPE_STRING,
4275+ G_TYPE_STRING);
4276+
4277+ signals[SOURCE_REMOVED] = g_signal_new ("source-removed",
4278+ IM_TYPE_APPLICATION_LIST,
4279+ G_SIGNAL_RUN_FIRST,
4280+ 0,
4281+ NULL, NULL,
4282+ g_cclosure_marshal_generic,
4283+ G_TYPE_NONE,
4284+ 2,
4285+ G_TYPE_STRING,
4286+ G_TYPE_STRING);
4287+
4288+ signals[MESSAGE_ADDED] = g_signal_new ("message-added",
4289+ IM_TYPE_APPLICATION_LIST,
4290+ G_SIGNAL_RUN_FIRST,
4291+ 0,
4292+ NULL, NULL,
4293+ g_cclosure_marshal_generic,
4294+ G_TYPE_NONE,
4295+ 10,
4296+ G_TYPE_STRING,
4297+ G_TYPE_STRING,
4298+ G_TYPE_STRING,
4299+ G_TYPE_STRING,
4300+ G_TYPE_STRING,
4301+ G_TYPE_STRING,
4302+ G_TYPE_STRING,
4303+ G_TYPE_VARIANT,
4304+ G_TYPE_INT64,
4305+ G_TYPE_BOOLEAN);
4306+
4307+ signals[MESSAGE_REMOVED] = g_signal_new ("message-removed",
4308+ IM_TYPE_APPLICATION_LIST,
4309+ G_SIGNAL_RUN_FIRST,
4310+ 0,
4311+ NULL, NULL,
4312+ g_cclosure_marshal_generic,
4313+ G_TYPE_NONE,
4314+ 2,
4315+ G_TYPE_STRING,
4316+ G_TYPE_STRING);
4317+
4318+ signals[APP_STOPPED] = g_signal_new ("app-stopped",
4319+ IM_TYPE_APPLICATION_LIST,
4320+ G_SIGNAL_RUN_FIRST,
4321+ 0,
4322+ NULL, NULL,
4323+ g_cclosure_marshal_VOID__OBJECT,
4324+ G_TYPE_NONE,
4325+ 1,
4326+ G_TYPE_STRING);
4327+
4328+ signals[REMOVE_ALL] = g_signal_new ("remove-all",
4329+ IM_TYPE_APPLICATION_LIST,
4330+ G_SIGNAL_RUN_FIRST,
4331+ 0,
4332+ NULL, NULL,
4333+ g_cclosure_marshal_VOID__VOID,
4334+ G_TYPE_NONE,
4335+ 0);
4336+}
4337+
4338+static void
4339+im_application_list_init (ImApplicationList *list)
4340+{
4341+ const GActionEntry action_entries[] = {
4342+ { "messages", NULL, NULL, "('', 'indicator-messages', 'Messages', true)", NULL },
4343+ { "remove-all", im_application_list_remove_all }
4344+ };
4345+
4346+ GSimpleActionGroup *actions;
4347+
4348+ list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free);
4349+
4350+ actions = g_simple_action_group_new ();
4351+ g_simple_action_group_add_entries (actions, action_entries, G_N_ELEMENTS (action_entries), list);
4352+
4353+ list->muxer = g_action_muxer_new ();
4354+ g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (actions));
4355+
4356+ g_object_unref (actions);
4357+}
4358+
4359+ImApplicationList *
4360+im_application_list_new (void)
4361+{
4362+ return g_object_new (IM_TYPE_APPLICATION_LIST, NULL);
4363+}
4364+
4365+static gchar *
4366+im_application_list_canonical_id (const gchar *id)
4367+{
4368+ gchar *str;
4369+ gchar *p;
4370+ int len;
4371+
4372+ len = strlen (id);
4373+ if (g_str_has_suffix (id, ".desktop"))
4374+ len -= 8;
4375+
4376+ str = g_strndup (id, len);
4377+
4378+ for (p = str; *p; p++)
4379+ {
4380+ if (*p == '.')
4381+ *p = '_';
4382+ }
4383+
4384+ return str;
4385+}
4386+
4387+static Application *
4388+im_application_list_lookup (ImApplicationList *list,
4389+ const gchar *desktop_id)
4390+{
4391+ gchar *id;
4392+ Application *app;
4393+
4394+ id = im_application_list_canonical_id (desktop_id);
4395+ app = g_hash_table_lookup (list->applications, id);
4396+
4397+ g_free (id);
4398+ return app;
4399+}
4400+
4401+void
4402+im_application_list_add (ImApplicationList *list,
4403+ const gchar *desktop_id)
4404+{
4405+ GDesktopAppInfo *info;
4406+ Application *app;
4407+ const gchar *id;
4408+
4409+ g_return_if_fail (IM_IS_APPLICATION_LIST (list));
4410+ g_return_if_fail (desktop_id != NULL);
4411+
4412+ if (im_application_list_lookup (list, desktop_id))
4413+ return;
4414+
4415+ info = g_desktop_app_info_new (desktop_id);
4416+ if (!info)
4417+ {
4418+ g_warning ("an application with id '%s' is not installed", desktop_id);
4419+ return;
4420+ }
4421+
4422+ id = g_app_info_get_id (G_APP_INFO (info));
4423+ g_return_if_fail (id != NULL);
4424+
4425+ app = g_slice_new0 (Application);
4426+ app->info = info;
4427+ app->id = im_application_list_canonical_id (id);
4428+ app->list = list;
4429+ app->actions = g_action_muxer_new ();
4430+ app->source_actions = g_simple_action_group_new ();
4431+ app->message_actions = g_simple_action_group_new ();
4432+ app->message_sub_actions = g_action_muxer_new ();
4433+
4434+ g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
4435+ g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
4436+ g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
4437+
4438+ g_hash_table_insert (list->applications, (gpointer) app->id, app);
4439+ g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions));
4440+}
4441+
4442+void
4443+im_application_list_remove (ImApplicationList *list,
4444+ const gchar *id)
4445+{
4446+ Application *app;
4447+
4448+ g_return_if_fail (IM_IS_APPLICATION_LIST (list));
4449+
4450+ app = im_application_list_lookup (list, id);
4451+ if (app)
4452+ {
4453+ if (app->proxy || app->cancellable)
4454+ g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id);
4455+
4456+ g_hash_table_remove (list->applications, id);
4457+ g_action_muxer_remove (list->muxer, id);
4458+ }
4459+}
4460+
4461+static void
4462+im_application_list_source_added (Application *app,
4463+ guint position,
4464+ GVariant *source)
4465+{
4466+ const gchar *id;
4467+ const gchar *label;
4468+ const gchar *iconstr;
4469+ guint32 count;
4470+ gint64 time;
4471+ const gchar *string;
4472+ gboolean draws_attention;
4473+ GVariant *state;
4474+ GSimpleAction *action;
4475+
4476+ g_variant_get (source, "(&s&s&sux&sb)",
4477+ &id, &label, &iconstr, &count, &time, &string, &draws_attention);
4478+
4479+ state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
4480+ action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state);
4481+ g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app);
4482+
4483+ g_simple_action_group_insert (app->source_actions, G_ACTION (action));
4484+
4485+ g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr);
4486+
4487+ g_object_unref (action);
4488+}
4489+
4490+static void
4491+im_application_list_source_changed (Application *app,
4492+ GVariant *source)
4493+{
4494+ const gchar *id;
4495+ const gchar *label;
4496+ const gchar *iconstr;
4497+ guint32 count;
4498+ gint64 time;
4499+ const gchar *string;
4500+ gboolean draws_attention;
4501+
4502+ g_variant_get (source, "(&s&s&sux&sb)",
4503+ &id, &label, &iconstr, &count, &time, &string, &draws_attention);
4504+
4505+ g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id,
4506+ g_variant_new ("(uxsb)", count, time, string, draws_attention));
4507+
4508+ g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr);
4509+}
4510+
4511+static void
4512+im_application_list_sources_listed (GObject *source_object,
4513+ GAsyncResult *result,
4514+ gpointer user_data)
4515+{
4516+ Application *app = user_data;
4517+ GVariant *sources;
4518+ GError *error = NULL;
4519+
4520+ if (indicator_messages_application_call_list_sources_finish (app->proxy, &sources, result, &error))
4521+ {
4522+ GVariantIter iter;
4523+ GVariant *source;
4524+ guint i = 0;
4525+
4526+ g_variant_iter_init (&iter, sources);
4527+ while ((source = g_variant_iter_next_value (&iter)))
4528+ {
4529+ im_application_list_source_added (app, i++, source);
4530+ g_variant_unref (source);
4531+ }
4532+
4533+ g_variant_unref (sources);
4534+ }
4535+ else
4536+ {
4537+ g_warning ("could not fetch the list of sources: %s", error->message);
4538+ g_error_free (error);
4539+ }
4540+}
4541+
4542+static gchar *
4543+get_symbolic_app_icon_string (GIcon *icon)
4544+{
4545+ const gchar * const *names;
4546+ gchar *symbolic_name;
4547+ GIcon *symbolic_icon;
4548+ gchar *str;
4549+
4550+ if (!G_IS_THEMED_ICON (icon))
4551+ return NULL;
4552+
4553+ names = g_themed_icon_get_names (G_THEMED_ICON (icon));
4554+ if (!names || !names[0])
4555+ return NULL;
4556+
4557+ symbolic_icon = g_themed_icon_new_from_names ((gchar **) names, -1);
4558+
4559+ symbolic_name = g_strconcat (names[0], "-symbolic", NULL);
4560+ g_themed_icon_prepend_name (G_THEMED_ICON (symbolic_icon), symbolic_name);
4561+
4562+ str = g_icon_to_string (symbolic_icon);
4563+
4564+ g_free (symbolic_name);
4565+ g_object_unref (symbolic_icon);
4566+ return str;
4567+}
4568+
4569+static void
4570+im_application_list_message_added (Application *app,
4571+ GVariant *message)
4572+{
4573+ const gchar *id;
4574+ const gchar *iconstr;
4575+ const gchar *title;
4576+ const gchar *subtitle;
4577+ const gchar *body;
4578+ gint64 time;
4579+ GVariantIter *action_iter;
4580+ gboolean draws_attention;
4581+ GSimpleAction *action;
4582+ GIcon *app_icon;
4583+ gchar *app_iconstr = NULL;
4584+ GVariant *actions = NULL;
4585+
4586+ g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)",
4587+ &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
4588+
4589+ app_icon = g_app_info_get_icon (G_APP_INFO (app->info));
4590+ if (app_icon)
4591+ app_iconstr = get_symbolic_app_icon_string (app_icon);
4592+
4593+ action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN);
4594+ g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);
4595+ g_simple_action_group_insert (app->message_actions, G_ACTION (action));
4596+
4597+ {
4598+ GVariant *entry;
4599+ GSimpleActionGroup *action_group;
4600+ GVariantBuilder actions_builder;
4601+
4602+ g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
4603+ action_group = g_simple_action_group_new ();
4604+
4605+ while ((entry = g_variant_iter_next_value (action_iter)))
4606+ {
4607+ const gchar *name;
4608+ GSimpleAction *action;
4609+ GVariant *label;
4610+ const gchar *type = NULL;
4611+ GVariant *hint;
4612+ GVariantBuilder dict_builder;
4613+ gchar *prefixed_name;
4614+
4615+ if (!g_variant_lookup (entry, "name", "&s", &name))
4616+ {
4617+ g_warning ("action dictionary for message '%s' is missing 'name' key", id);
4618+ continue;
4619+ }
4620+
4621+ label = g_variant_lookup_value (entry, "label", G_VARIANT_TYPE_STRING);
4622+ g_variant_lookup (entry, "parameter-type", "&g", &type);
4623+ hint = g_variant_lookup_value (entry, "parameter-hint", NULL);
4624+
4625+ action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL);
4626+ g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);
4627+ g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);
4628+ g_simple_action_group_insert (action_group, G_ACTION (action));
4629+
4630+ g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));
4631+
4632+ prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL);
4633+ g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));
4634+
4635+ if (label)
4636+ {
4637+ g_variant_builder_add (&dict_builder, "{sv}", "label", label);
4638+ g_variant_unref (label);
4639+ }
4640+
4641+ if (type)
4642+ g_variant_builder_add (&dict_builder, "{sv}", "parameter-type", g_variant_new_string (type));
4643+
4644+ if (hint)
4645+ {
4646+ g_variant_builder_add (&dict_builder, "{sv}", "parameter-hint", hint);
4647+ g_variant_unref (hint);
4648+ }
4649+
4650+ g_variant_builder_add (&actions_builder, "a{sv}", &dict_builder);
4651+
4652+ g_object_unref (action);
4653+ g_variant_unref (entry);
4654+ g_free (prefixed_name);
4655+ }
4656+
4657+ g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group));
4658+ actions = g_variant_builder_end (&actions_builder);
4659+
4660+ g_object_unref (action_group);
4661+ }
4662+
4663+ im_application_list_update_draws_attention (app->list);
4664+
4665+ g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
4666+ app->id, app_iconstr, id, iconstr, title,
4667+ subtitle, body, actions, time, draws_attention);
4668+
4669+ g_variant_iter_free (action_iter);
4670+ g_free (app_iconstr);
4671+ g_object_unref (action);
4672+}
4673+
4674+static void
4675+im_application_list_messages_listed (GObject *source_object,
4676+ GAsyncResult *result,
4677+ gpointer user_data)
4678+{
4679+ Application *app = user_data;
4680+ GVariant *messages;
4681+ GError *error = NULL;
4682+
4683+ if (indicator_messages_application_call_list_messages_finish (app->proxy, &messages, result, &error))
4684+ {
4685+ GVariantIter iter;
4686+ GVariant *message;
4687+
4688+ g_variant_iter_init (&iter, messages);
4689+ while ((message = g_variant_iter_next_value (&iter)))
4690+ {
4691+ im_application_list_message_added (app, message);
4692+ g_variant_unref (message);
4693+ }
4694+
4695+ g_variant_unref (messages);
4696+ }
4697+ else
4698+ {
4699+ g_warning ("could not fetch the list of messages: %s", error->message);
4700+ g_error_free (error);
4701+ }
4702+}
4703+
4704+static void
4705+im_application_list_unset_remote (Application *app)
4706+{
4707+ gboolean was_running;
4708+
4709+ was_running = app->proxy || app->cancellable;
4710+
4711+ if (app->cancellable)
4712+ {
4713+ g_cancellable_cancel (app->cancellable);
4714+ g_clear_object (&app->cancellable);
4715+ }
4716+ g_clear_object (&app->proxy);
4717+
4718+ /* clear actions by creating a new action group and overriding it in
4719+ * the muxer */
4720+ g_object_unref (app->source_actions);
4721+ g_object_unref (app->message_actions);
4722+ g_object_unref (app->message_sub_actions);
4723+ app->source_actions = g_simple_action_group_new ();
4724+ app->message_actions = g_simple_action_group_new ();
4725+ app->message_sub_actions = g_action_muxer_new ();
4726+ g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
4727+ g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
4728+ g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
4729+
4730+ im_application_list_update_draws_attention (app->list);
4731+
4732+ if (was_running)
4733+ g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id);
4734+}
4735+
4736+static void
4737+im_application_list_app_vanished (GDBusConnection *connection,
4738+ const gchar *name,
4739+ gpointer user_data)
4740+{
4741+ Application *app = user_data;
4742+
4743+ im_application_list_unset_remote (app);
4744+}
4745+
4746+static void
4747+im_application_list_proxy_created (GObject *source_object,
4748+ GAsyncResult *result,
4749+ gpointer user_data)
4750+{
4751+ Application *app = user_data;
4752+ GError *error = NULL;
4753+
4754+ app->proxy = indicator_messages_application_proxy_new_finish (result, &error);
4755+ if (!app->proxy)
4756+ {
4757+ if (error->code != G_IO_ERROR_CANCELLED)
4758+ g_warning ("could not create application proxy: %s", error->message);
4759+ g_error_free (error);
4760+ return;
4761+ }
4762+
4763+ indicator_messages_application_call_list_sources (app->proxy, app->cancellable,
4764+ im_application_list_sources_listed, app);
4765+ indicator_messages_application_call_list_messages (app->proxy, app->cancellable,
4766+ im_application_list_messages_listed, app);
4767+
4768+ g_signal_connect_swapped (app->proxy, "source-added", G_CALLBACK (im_application_list_source_added), app);
4769+ g_signal_connect_swapped (app->proxy, "source-changed", G_CALLBACK (im_application_list_source_changed), app);
4770+ g_signal_connect_swapped (app->proxy, "source-removed", G_CALLBACK (im_application_list_source_removed), app);
4771+ g_signal_connect_swapped (app->proxy, "message-added", G_CALLBACK (im_application_list_message_added), app);
4772+ g_signal_connect_swapped (app->proxy, "message-removed", G_CALLBACK (im_application_list_message_removed), app);
4773+
4774+ g_bus_watch_name_on_connection (g_dbus_proxy_get_connection (G_DBUS_PROXY (app->proxy)),
4775+ g_dbus_proxy_get_name (G_DBUS_PROXY (app->proxy)),
4776+ G_BUS_NAME_WATCHER_FLAGS_NONE,
4777+ NULL, im_application_list_app_vanished,
4778+ app, NULL);
4779+}
4780+
4781+void
4782+im_application_list_set_remote (ImApplicationList *list,
4783+ const gchar *id,
4784+ GDBusConnection *connection,
4785+ const gchar *unique_bus_name,
4786+ const gchar *object_path)
4787+{
4788+ Application *app;
4789+
4790+ g_return_if_fail (IM_IS_APPLICATION_LIST (list));
4791+
4792+ app = im_application_list_lookup (list, id);
4793+ if (!app)
4794+ {
4795+ g_warning ("'%s' is not a registered application", id);
4796+ return;
4797+ }
4798+
4799+ if (app->cancellable)
4800+ {
4801+ gchar *name_owner = NULL;
4802+
4803+ if (app->proxy)
4804+ name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy));
4805+ g_warning ("replacing '%s' at %s with %s", id, name_owner, unique_bus_name);
4806+
4807+ im_application_list_unset_remote (app);
4808+
4809+ g_free (name_owner);
4810+ }
4811+
4812+ app->cancellable = g_cancellable_new ();
4813+ indicator_messages_application_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
4814+ unique_bus_name, object_path, app->cancellable,
4815+ im_application_list_proxy_created, app);
4816+}
4817+
4818+GActionGroup *
4819+im_application_list_get_action_group (ImApplicationList *list)
4820+{
4821+ g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), NULL);
4822+
4823+ return G_ACTION_GROUP (list->muxer);
4824+}
4825
4826=== added file 'src/im-application-list.h'
4827--- src/im-application-list.h 1970-01-01 00:00:00 +0000
4828+++ src/im-application-list.h 2013-07-12 19:50:34 +0000
4829@@ -0,0 +1,52 @@
4830+/*
4831+ * Copyright 2012 Canonical Ltd.
4832+ *
4833+ * This program is free software: you can redistribute it and/or modify it
4834+ * under the terms of the GNU General Public License version 3, as published
4835+ * by the Free Software Foundation.
4836+ *
4837+ * This program is distributed in the hope that it will be useful, but
4838+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4839+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
4840+ * PURPOSE. See the GNU General Public License for more details.
4841+ *
4842+ * You should have received a copy of the GNU General Public License along
4843+ * with this program. If not, see <http://www.gnu.org/licenses/>.
4844+ *
4845+ * Authors:
4846+ * Lars Uebernickel <lars.uebernickel@canonical.com>
4847+ */
4848+
4849+#ifndef __IM_APPLICATION_LIST_H__
4850+#define __IM_APPLICATION_LIST_H__
4851+
4852+#include <gio/gio.h>
4853+
4854+#define IM_TYPE_APPLICATION_LIST (im_application_list_get_type ())
4855+#define IM_APPLICATION_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_TYPE_APPLICATION_LIST, ImApplicationList))
4856+#define IM_APPLICATION_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IM_TYPE_APPLICATION_LIST, ImApplicationListClass))
4857+#define IM_IS_APPLICATION_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_TYPE_APPLICATION_LIST))
4858+#define IM_IS_APPLICATION_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_TYPE_APPLICATION_LIST))
4859+#define IM_APPLICATION_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_TYPE_APPLICATION_LIST, ImApplicationListClass))
4860+
4861+typedef struct _ImApplicationList ImApplicationList;
4862+
4863+GType im_application_list_get_type (void);
4864+
4865+ImApplicationList * im_application_list_new (void);
4866+
4867+void im_application_list_add (ImApplicationList *list,
4868+ const gchar *desktop_id);
4869+
4870+void im_application_list_remove (ImApplicationList *list,
4871+ const gchar *id);
4872+
4873+void im_application_list_set_remote (ImApplicationList *list,
4874+ const gchar *id,
4875+ GDBusConnection *connection,
4876+ const gchar *unique_bus_name,
4877+ const gchar *object_path);
4878+
4879+GActionGroup * im_application_list_get_action_group (ImApplicationList *list);
4880+
4881+#endif
4882
4883=== added file 'src/im-phone-menu.c'
4884--- src/im-phone-menu.c 1970-01-01 00:00:00 +0000
4885+++ src/im-phone-menu.c 2013-07-12 19:50:34 +0000
4886@@ -0,0 +1,331 @@
4887+/*
4888+ * Copyright 2012 Canonical Ltd.
4889+ *
4890+ * This program is free software: you can redistribute it and/or modify it
4891+ * under the terms of the GNU General Public License version 3, as published
4892+ * by the Free Software Foundation.
4893+ *
4894+ * This program is distributed in the hope that it will be useful, but
4895+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4896+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
4897+ * PURPOSE. See the GNU General Public License for more details.
4898+ *
4899+ * You should have received a copy of the GNU General Public License along
4900+ * with this program. If not, see <http://www.gnu.org/licenses/>.
4901+ *
4902+ * Authors:
4903+ * Lars Uebernickel <lars.uebernickel@canonical.com>
4904+ */
4905+
4906+#include "im-phone-menu.h"
4907+
4908+#include <string.h>
4909+
4910+typedef GObjectClass ImPhoneMenuClass;
4911+
4912+struct _ImPhoneMenu
4913+{
4914+ GObject parent;
4915+
4916+ GMenu *toplevel_menu;
4917+ GMenu *message_section;
4918+ GMenu *source_section;
4919+
4920+};
4921+
4922+G_DEFINE_TYPE (ImPhoneMenu, im_phone_menu, G_TYPE_OBJECT);
4923+
4924+typedef void (*ImMenuForeachFunc) (GMenuModel *menu, gint pos);
4925+
4926+static void
4927+im_phone_menu_foreach_item_with_action (GMenuModel *menu,
4928+ const gchar *action,
4929+ ImMenuForeachFunc func)
4930+{
4931+ gint n_items;
4932+ gint i;
4933+
4934+ n_items = g_menu_model_get_n_items (menu);
4935+ for (i = 0; i < n_items; i++)
4936+ {
4937+ gchar *item_action;
4938+
4939+ g_menu_model_get_item_attribute (menu, i, G_MENU_ATTRIBUTE_ACTION, "s", &item_action);
4940+
4941+ if (g_str_equal (action, item_action))
4942+ func (menu, i);
4943+
4944+ g_free (item_action);
4945+ }
4946+}
4947+
4948+static void
4949+im_phone_menu_update_toplevel (ImPhoneMenu *menu)
4950+{
4951+ if (g_menu_model_get_n_items (G_MENU_MODEL (menu->message_section)) ||
4952+ g_menu_model_get_n_items (G_MENU_MODEL (menu->source_section)))
4953+ {
4954+ if (g_menu_model_get_n_items (G_MENU_MODEL (menu->toplevel_menu)) == 0)
4955+ {
4956+ GMenuItem *item;
4957+
4958+ g_menu_append_section (menu->toplevel_menu, NULL, G_MENU_MODEL (menu->message_section));
4959+ g_menu_append_section (menu->toplevel_menu, NULL, G_MENU_MODEL (menu->source_section));
4960+
4961+ item = g_menu_item_new ("Clear All", "remove-all");
4962+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.button");
4963+ g_menu_append_item (menu->toplevel_menu, item);
4964+
4965+ g_object_unref (item);
4966+ }
4967+ }
4968+ else
4969+ {
4970+ while (g_menu_model_get_n_items (G_MENU_MODEL (menu->toplevel_menu)))
4971+ g_menu_remove (menu->toplevel_menu, 0);
4972+ }
4973+}
4974+
4975+static void
4976+im_phone_menu_dispose (GObject *object)
4977+{
4978+ ImPhoneMenu *menu = IM_PHONE_MENU (object);
4979+
4980+ g_clear_object (&menu->toplevel_menu);
4981+ g_clear_object (&menu->message_section);
4982+ g_clear_object (&menu->source_section);
4983+
4984+ G_OBJECT_CLASS (im_phone_menu_parent_class)->dispose (object);
4985+}
4986+
4987+static void
4988+im_phone_menu_finalize (GObject *object)
4989+{
4990+ G_OBJECT_CLASS (im_phone_menu_parent_class)->finalize (object);
4991+}
4992+
4993+static void
4994+im_phone_menu_class_init (ImPhoneMenuClass *klass)
4995+{
4996+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
4997+
4998+ object_class->dispose = im_phone_menu_dispose;
4999+ object_class->finalize = im_phone_menu_finalize;
5000+}
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: