pax_global_header00006660000000000000000000000064126027662360014524gustar00rootroot0000000000000052 comment=3acac258566543b3829a94108deb84b6af439d78 corebird-1.1/000077500000000000000000000000001260276623600131565ustar00rootroot00000000000000corebird-1.1/._vimrc000066400000000000000000000001421260276623600144330ustar00rootroot00000000000000set wildignore+=*.c,*\~,CMakeFiles,Makefile,*.lo,test-driver,*.trs,*.stamp,Makefile.in,*.la,*.svg corebird-1.1/.gitignore000066400000000000000000000011101260276623600151370ustar00rootroot00000000000000corebird Corebird.db src/*.c Corebird src/widgets/*.c src/containers/*.c src/util/*.c *.c *.o *.lo *.la .dirstamp *.stamp *.stamp-t .deps Makefile.in m4/ src/sql/*.c CMakeFiles Makefile src/Makefile src/*.cmake assets/avatars/* assets/banners/* assets/user/* stats *.swp src/util/Config.vala session.vim *~ aclocal.m4 compile config.guess config.log config.status config.sub configure autom4te.cache depcomp install-sh ltmain.sh missing libtool ChangeLog INSTALL intltool-extract.in intltool-merge.in intltool-update.in config.rpath test-driver .libs src/corebird.h src/corebird.vapi corebird-1.1/COPYING000066400000000000000000001045131260276623600142150ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . corebird-1.1/Makefile.am000066400000000000000000000006041260276623600152120ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SUBDIRS = src ui data assets po tests sql EXTRA_DIST = config.rpath \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ resources.xml DISTCLEANFILES = \ intltool-extract \ intltool-merge \ intltool-update \ po/.intltool-merge-cache AUTOMAKE_OPTIONS = subdir-objects corebird-1.1/README.md000066400000000000000000000066611260276623600144460ustar00rootroot00000000000000# Corebird This is the readme for version 1.1. [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=baedert&url=http://github.com/baedert/corebird&title=corebird&language=vala&tags=github&category=software) ## Shortcuts | Key | Description | | :-----: | :----------- | | `Ctrl + t` | Compose Tweet | | `Back` | Go one page back (this can be triggered via the back button on the keyboard, the back thumb button on the mouse or `Alt + Left`) | | `Forward` | Go one page forward (this can be triggered via the forward button on the keyboard, the forward thumb button on the mouse or `Alt + Right`) | | `Alt + num` | Go to page `num` (between 1 and 7 at the moment) | | `Ctrl + Shift + s` | Show/Hide sidebar | | `Ctrl + p` | Show account settings | | `Ctrl + k` | Show account list | | `Ctrl + Shift + p` | Show application settings | When a tweet is focused (via keynav): - `r` - reply - `tt` - retweet - `f` - favorite - `dd` - delete - `Return` - Show tweet details ## Will this work on distribution XYZ? I don't know. If you can satisfy all the dependencies, probably yes but you'd most likely still have to compile and install it from source (that is, if no one else makes packages). ## Translations Since February 2014, there's a [Corebird project on Transifex](https://www.transifex.com/projects/p/corebird) ## Contributing All contributions are welcome (artword, design, code, just ideas, etc.) but if you're planning to actively change something bigger, talk to me first. ## Dependencies - `gtk+-3.0 >= 3.16` - `glib-2.0 >= 2.44` - `rest-0.7` (`>= 0.7.91` for image uploads) - `json-glib-1.0` - `sqlite3` - `libsoup-2.4` - `intltool >= 0.40` - `libgee-0.8` - `vala >= 0.26` (makedep) - `automake >= 1.14` (makedep) - `gstreamer-1.0` (disable via --disable-video, default enabled) - `gst-plugins-bad-1.0` (disable via --disable-video, default enabled) - `gst-plugins-good-1.0` (disable via --disable-video, default enabled) - `gst-libav-1.0` (disable via --disable-video, default enabled) Note that the above packages are just rough estimations, the actual package names on your distribution may vary. If you pass `--disable-video` to the configure script, you don't need any gstreamer dependency but won't be able to view any videos (i.e. no vines and no twitter gifs). ## Compiling ``` ./autogen.sh --prefix=/usr make make install ``` corebird-1.1/assets/000077500000000000000000000000001260276623600144605ustar00rootroot00000000000000corebird-1.1/assets/128x128/000077500000000000000000000000001260276623600154155ustar00rootroot00000000000000corebird-1.1/assets/128x128/Makefile.am000066400000000000000000000001231260276623600174450ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/128x128/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/128x128/corebird.png000066400000000000000000000325571260276623600177300ustar00rootroot00000000000000PNG  IHDR>abKGD IDATx}y$EEdf]=0= \. 0Êˢ,Vum^]uZ9TPSq?"*" ssY]WfYUOOUeFfŻ Ex^]/4lӅH\/TJ)ff @ZB{kCt5Z.Qn|)țTA+߽1Jebo{GYs0jƎ8xw.C-]jt/@&!lКEŔ֬:uņF)k8+aT! \Wkj*l褹S_z~!\;jufF\Dѓy)iVOu zA" {1<\AlB.P|"uw9Ǝ e̐Re2C-TBTkT1ϑ})i3#088"*jaVP0\,oő2YOt@$Ėʦ:{]l FE\M?O$(te@$ߝzO@bxx'-j%D+L7a 70VJZp8}–#fAV M5>#mvJ`Z 彁FO 4nQ(̭C FR|n0ZКQ,02|OZiDBF`cX,#!:I\f#lhV$]G J ´/\U\G5ҲfH+( 0k0<)Q¤01G&<a 5P`fN &R;Lo(Rg8ETZ{R(te@zB h %ifA>*V _k'aڬ}3raYy2 *UԪ8g~!tx(߈/)Ӫh֟#ɊpW%g+hCC%݅,2嫡°} 1Ɉ'[G ([r4ҌT+a=[s/rџMO2Akncd:~9dJjO/.HDhn !r@YDW*_KێaZX}B֚OƏ6!! Օ0R `C@ /рH,4{$zf2T0Ή$wu]YCAZr=LR1s~zO)מr`@W.^j5RA࣐ ݬh@ҌJ `XF7k mz(&`9RJZRؙy()Q)Yp"+=O@PB.nbZ@xߓf}PJ\._ߋsx2ߗW|]QR  Y̘G$t:\,Cq(nO="3 HadrrR.# WȌHߓѝ3oR~U=L9\vt3#xfQZyxf W(]H]gRTKA\C0J#ZhDWe9I`')d T~󷵇)'9Yh IA6 IDLIk?0iFqp=r, 2 QU#J?Е7-a= fkQ)(%c1܎=ffQFR Q*W(dn2Ƒ# ɾhOkQ/Fql>{Kxl 1H PT!j 6; Tk_b<FQ1c”*lu9 TPԴ_!\!)h"գQ)3&\+<,ʾD6E ГٮVDja ڍS0"`%%mm%f# q /f)Y_=$( Wy MF 2~շ7d^+؂lAbJBȦW`W]p.ڽͮ\.@Eό}8 1C3 ž#Ub`P:)fM{ ӗkȲu7R\ lB9emů*(T]IZx|1~K@#nTCk4XG¢.b]J kz?h/!=p-G|ؔ 5BC $ p.V0f 7V :j0iX_r>FGQ !|BiUaAF*XX"N ̨^B6Bbk.s9lgQ$>D;Jv -$MM5T5;>}RI&M>{)Ps:3**UBQaJ {TC#S,clbz+n`}Ġ`g6@_.@A$ HV;H% G @QVG{NJ =c\ԛC$<} G?k<&*VaFF+btE!] 5To\A$BJA"H_bDJ}!P=ጇAFy7b&P$Z]R OQ+m >K|9@ܭm8E]ˌ)@6Iirl :'qD\ =97lݩ}k4!hɁzS2ruz@RFF E"4CzH NNC|ݣd؉XC)!@1 U"# b$דW K X]Vq =lv@(n콠V0!pѧ)R>&Jk(u?3cB"MfNn "d2i&Dt 0kܠ%L!nw1bF+/!cr=o=~v(xɯF:0ZCs̟QEP:6Ϻ1+L[%qjnk h #(A+ie"[om2`mIPJ;^𾥽=^\r!G2i]AVlY)˩fR;m=U&I@͎՛bM"", kfe~C7l ;I pzL̉v\&Q]A5]E \Wo'Zh mBH-a 2 0^D3a5<¼R TJ5l+bp "H &"RKZBP;cZ b9 szD-R.װq0S?`<{@ ɔHiŽp w߃Q KJ•lޗUQ<Ĭ5ٚyZYИݝqǑ ~52^>Xl `IZBH~f+$zY2QZaf1Qg!*xn+~j {f+"@9,(Ԃ fc`!qq>[/d eĊ;Z%U ĒNa⧏>>!f&6FǮjv̞}taڳ p#P)!ҋEAܢVylc$V#}`+`nt#ko$`.@n$5sJQR YK>o9̟=AL6Så2mZ5 |80̗anoG}wéGb5]`)Ս[R&qclxoG:&7O=0Dث;CiN?dߙͯKqǂ8yX8XZ:QZM|&8p&:G/mAx']`aN#Еi=ɮ^ٹ)XHنĎDоJ׮19%= B"i"iۧ/XSxxG"vXugv _6^EfzXuIh-ĬJ'֟ ov:$"qt}%Z[G~'N;zfte|qB֒!zz jp@b뮸uvI|-S m@[&hsKƪom݂?X ĮjVMwh%!ڵcsgy 6'r-03Ts0gƟs!HV?pq}CS ׁ5.9%שO*}(CY1`cp݀z,ı/hW_{`&0m]McbOjT0^~5|hvsl[DӜ^(k`0-\gsdmNqYο;8v+Efv0kRs˅O,R,둯¢}*S6o|;sp`I5ӫQ)c+<ipe:*n3/*@$=NGOhW_[4= vi۟+$|15]u?(V|O]RSÿ[qȢ~/>}÷jƺL眊'|?lfD#H[jmERF"!uS|fOnO]-WB>(q߽r;z_郟;j ߻'8e;$[ VڭȚm>t 6@[LFT'1wvW& _p.rT*U}W㗿~|w^yW~2f}+Mw0+ OkJ) KS'NB|H.]R\Y.Yk[wcO@{57~O0{?yDm>?⿾s;`x}/嫰n3~=I@.#- 0eF~L?k$x˵-(Mvv_őfcFu)|{wR^WguvglOkHos.^<~ Z>?Z7^ԃ[;`!?^>674X--ZI7,z]g[:>$u[as}y,3g=^|xeO850;\u-4jBp+i0,ŚKa5O(ߔ=/|/?wP66GPC#zvi6t!%DQqxr׈j# rvo#:Re/0:'<9sԂ#&aA?}=L?j\&bcP4=m#۷XV|Pn=ڐL5 =>͟ӅYtzxRIR"U)-w Qn;b |#E[v nBpM2gLD3N3gL( ngytwgq1f0QlYiMP@vۦmW\vy"~rkd7/9dfXÅz%8 WuPKBk2Zf76eشiS,̜эW^ql6]޶[Y?s:~g|g[ARF>l5M'Ka&t! ߮α#[?[cvc qNcݺ\3qGyY]wr:lј]lr{uk5璤qb's)[A96`~9o0 7, 1!2!}TպN%t Ī8pa>z$V68 ;~ |(JA03zWLmgcӳضm[[̓~sO:-f㈍44ƪía|O#SE:Ep[QӦO\ׇj~[@RB mS0"nEjWqch̷&F} %M?aŁ Hf=Zbǎ4jnM|5_6rʵK2 S9kl;Jc4/s r@dr@oDd϶mP.`ZZbظq#q'ٜ4036n/l+IIVg+ G ~A?c[q`_͖@==LV B4m|gGƺu֯_g}[n֮]5kLb,ؼysǝ.Rի4`eǞ@gAI:΁Z' TH/5*"D@dY㫶QaBJ_sx1D~իK3kZ۱uVſɓbO + M"&T0A#t"zO,E'؎YѳրpP c{96-@>CrW6Nj}@qᘭC}9AV< Al 1`==ba˖-ؾؿ?m* '2lN:kA씾kVm!ˊ1_+-8Sd\No4DPVzz8I`=WOßc>#5Ћgt'N4*#!?z ^z)仌Yd W%ܰqۧqKO m>/@0MG*X/ J) k 9Qc?\BX!‘N0<=7g!*=UG:q?;<<5k4UtCXGKe1 ue4\!v!!Ϗ}^˯8-؆8V`M:y=l̠!ӃB(AmG_HC"]wP(m0ZZ;G4>_Y/y%g !MnTX۶Uw^cӄWsAG%Nq J9>07_ɀh|oź b]]ĉtbϞ=u!$sH0 t&_yͲ/Lh3v >ӫi31/EJH+D@e =]H@J<v_M!<?dH/|7ფgaiM?$t a=D#⋓ߤ jB!Yلj"pELE2E!!>E [W\c.c @ҳD!^{&)>}DYcNV4@& 1s[/$}L.  C "oqU( "RX$7̬w$MߝY[_CTo#}9b7uyޓ>eAm7շ\T ٠t N$SĚI$ c} 2g9.cdv

k?=9}ϊe3TL'm=!-"ҙChe-8?A(T|$ 7x`ùRsZ#>  j}/C$ S !'b{&s{{yW/ti]|+k~/+J)k$AKBp_R\caIf!I co@ЕJ 9eѐ!<Ƨ"c+eݶw :Nಿmg o'_iAϻA+UUv'Q&,1 8u8,ů\u#agmYpj7^=IX)a-Ĺw^ϴCb֪>4uHu4CNk@#}$+~?ѺrEb8;̨ykH`m$pV,scda~չRJc b[ -PI)~6n,s/3Spc9KIToa.}ȝtemuO2ۯ[KOә:R[V/`kj+_6`oDB߉]\V<1Ok& ~Yp2Nh8L N05Spm׾iCBR[W#X\H wt{a),π& lΜ0$b " p?!0>Bfg.V!FZ< 7_ @8=8OlP.e7w<`S /H3E'W`>Mf$q}O nPX۷^/h={CȠ1Y}$sv ;W٭N4Xֳh h-Nv Z񺟕UxChkI`;ie?LX528w}'tTEyWiW *-bh#gBmH6ɬq"H9})_S% FxE@#}mK毒.XDmQ.`2qJ<4T G#5F&KгBD(n|.}SP|C9k|C'KI[Hxo%? xE@#z8 7Q@UAqx `xzBC+t8k~ `d#֯EW=T1BZGbq!ql!sv0s~|N8@^[s V) B(\I10XEPQ#ЯD!;p0J[Byܿ,/c!Hz b'煀?;g|<0`2`l0J.AdDǪo6˭3A#FuhbhPZ١c'd\`$T>ϫ7~e%o*Ϛrb| dU8X !PkU :Ø)fLL,|O fGLZ6KP 36Dcۯ]16pp櫉&uD)Q`YAG!<'N ]hXB + { .E[l6A:d]w|ms9_8xVF'JM& \.׳E>vʵx'X]?,=MoSW<`/+o931΄raG2(E\rԍۉ>zxqJ/>{=@K_S+;M)X[|93R)aIjkw.--Ra}S?~{ zᯆpn>5.$-l)d@ZHopkFoٕK* w,p`c a ꞻ{CCᯜFy5JAY(O;b3u}vEx^Ex jꄰ2IENDB`corebird-1.1/assets/16x16/000077500000000000000000000000001260276623600152455ustar00rootroot00000000000000corebird-1.1/assets/16x16/Makefile.am000066400000000000000000000001211260276623600172730ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/16x16/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/16x16/corebird.png000066400000000000000000000014631260276623600175500ustar00rootroot00000000000000PNG  IHDRabKGDIDAT8uOlTeͿڙ)tj?4hűjM*Qd;RwJm4ea UU$IXiR)d0cg7 )ݽ9ܓ{%05Oa(,ŕ; b NWk6{?"OJ CG:,Zs`m0͍| a0ֲ|dBPT =/{nI;86Q8a|%Jմec񘹒$k֕yWVV긃N)VN."y@&2{~d*b>{{֓Mо봭urp,?Ve'*zҾ2~S90d&MLbCDoΡ({Ӵ3FJm͕><&':ͮg=>@1S\Kg>9 L²Lnmb淒J&8?5?qšWa*4u }] OS46d/W: 9uGQ~@9yb!]fE0|?Q:s:O7 >y-qk|M gRh_^qݦ"gvrvZDJ&h"눬-Fy-_L?xoΧߗ.%7djGCg7ѳxy|q@ťxH?ȳIENDB`corebird-1.1/assets/24x24/000077500000000000000000000000001260276623600152435ustar00rootroot00000000000000corebird-1.1/assets/24x24/Makefile.am000066400000000000000000000001211260276623600172710ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/24x24/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/24x24/corebird.png000066400000000000000000000026161260276623600175470ustar00rootroot00000000000000PNG  IHDRw=bKGDCIDATHlU?キmۍ.:s%f!qaӰi.!!0$` H܂ 5ˆ(~ȏLdsmZgۭv?{w{}{WkX,&?vL<8W`g 3f曙̀ꖪ֏xrMݟ8W>ɞ}82b""7z){[\EKJ 4*XyI&|<ϲEtYZ:2Mi1dpǍLL QUX'+8Lٴnˮ鸤~pݗčy֝z!!ıve<ᓼ6%kaI'ܧZjէ깋܌h_pc?ѡQ>'H %B\y; `u5k[^^|T/цhÚf\ NQP;m\K.7n8^&艂pAD)Ei2U ~r.W)X={_ͯx;*qUDhܐvO yOMqr\J0Z+wwo#nI&ygƣWۺe7<IIENDB`corebird-1.1/assets/256x256/000077500000000000000000000000001260276623600154215ustar00rootroot00000000000000corebird-1.1/assets/256x256/Makefile.am000066400000000000000000000001231260276623600174510ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/256x256/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/256x256/corebird.png000066400000000000000000001107271260276623600177300ustar00rootroot00000000000000PNG  IHDR\rfsBIT|d pHYsmhtEXtSoftwarewww.inkscape.org< IDATx}ydEuT7oaQEqPvq\5q%ш 3~&& |QӘ.}Gթׯ6=u9w:,-------Áh@s02:NeM`ض#uO|۸@á0'oԉ = s{ۮ>f 4uZS vY_I [̕sQE"̻wf٦o|Ɇ =MÈkNvF08F?(N#pYc?їyÄ~q,[Wf<2òEEV@=ҵ\"@@-=?{%gix-L>WkO*XgAsqyɹ5g(Bn_w~t> F `뽀 ۴ܸK.P^y+[w=q6[0ŃHAJ=;gw@ Sz?o!u  ؠ{ ʲ#I-a {^,7dFL?ƈvw`bl+/lO0&@p)(R{@pKIq<,l2-,BD@֜tޙ 7-Y+o.YDx Y,ePN:-:;1'ƍ`N1mMw*DWޓ4~C -qZ_[ a k,AY1}mOO.diA]'[H):-/7lvl* Nlt*1YUS/AA+j _ f5˰@[MG70>\Q6 k`"Pgkۃ7K%0kH8R#r q1QבgrZZCk/'R=% RʷU)j2 XXȭ3݁2s. &݁ 4tzX"+tUhHG0`eC3WӮ+u#{̛}5V_W[,>'ooa7 ȧzݙ T̓vyJ=ރP7|[0֙Xƀ-V] H~c<;iɝ_(4jb3if{/w[sck|k7=lgGZ\i 6Es<0݀=o|C?s_uKY9&/aϼw!M١k~`m/h2@Jo~fH c乁lSφ@h,u_ݲ=۔K`ď0 9Gɇ(o ϻЛu8S̀,s@ 25>ZX_|GF%WzY9%%@lx5A(PT(x a Xׯyn f'R b˗(9PH 'IGD/LRm˦Wo+ؠ?uW,7kDI~'R1ta$w=A)P`0(:HJ}VkQdyL;Z-S-U5h@<L 2z`]PnaM_#8'7L\.D*y"Y9L ١qܞvp)K609J<]r6voo[8< `xwna,%efU;,`V Y3gjXk7S嫚N/qyVᄒǡYrENX.h\ߓw~Jؔǒ脡BZpxA zs0 g> ~t6m7'}ȬM?ϭs4 7-Yp;$16Pt#Jmska P-V#ٔf[ætc/0uvT{s3xHfЀ5GØ ĭZCM3 %u  Az~]7iL}鏹>yoȴΜp*0d]GpFJ|ND1 ơZ'B}6V6FMu r聊c΋C]w?n\'g 9yK kEȴF!S.AF"")Z]!  l;oa;s'Z-~"}3혯R1 !z2? AōAkMheZ m!wJ+dHf?bVN E>J}=A8.R~'co?c`w}$ G&U^HB-i´i8KkL$!C,jw0Ka" ~IixQŒ I0"lXN u22LtK!Y<;[1 M Q'#!^SK,3ex-An AvɻvOs7 HmՒby ‘_Q2 i(= g"XN|;VO&!<;mޛ4>Kk OC`ʋP!c j[$a+=@(6.(|u1_ v{o"9 > Ǩ#$PwxiHۂdߙJ)Z Xvk,"(PYɶ(\`@Zml("SYn|y$+\ ?=C* #7{Vn[ܰ˂3. f>4g]R-CX6v :]t9]scl]wňpLY)(41ZEAODj ˻ 6Brnj#ObD~rBX Vy)hfΜƆrĽ,(( ^k[ 8)bKؿ e&$F/v$ @L%D)ޢeQ_񀤪2;fZn{[kz;a.H†r3%=ChrgtY-%fys2ս["˔sR2 <ʣ>ݪyIܯi%mHSOu(uq>oasܸP3u\0܄B} `-4MҜ[;'+T!ɟ/y!m2%a`A6>wB-iD{ &AH]u#%&o1wiDu`:S.SI00k?Y$@yL 6_?]_ y=4nkn1IJ|EUZigl2%ed%#(0\9D va-0KX(åP33ڭ,MB8DI)NxJIMd mP  jaҕGmXB/,@Z"/e܀^[HHɝ+'ۂȽ972cm yi-)~N{)0T֕b5QvtϜ+JzZ)_J/ }~0FXg7uDI@δςx&Mu˕{yagXEr$N>c<)2>|kcG=] WDv­%xZ P94bnNuU̧ۭrhzxmv5\C,ɼ ^|6e׍(Q`* 8BDK[t "B@("I/毡N}գ꾺߽=[gkEƠi{HVw6DR $BJH]}xꕻ|)97ohEqU;g8Ͼh'ؿ%d.|tKPw6&9WM^ԧ拿MJh+zdT5"#5-tKӦ^dm]~BXz|v P0!Pq芰Xj@xI 2?k;gJ}e 7S4o}Tf;b{g 2ϤJ4u 9W}g[ vۥ V桻F~?`c.V̋O\ڿdi"(a=P"oRЙL_c~ /VBܢ1[r&cƒ8@ubȍ}>~8[4o€Jw[c04__iy&I),z)%Ûv\lB⋅b:,3LiemM{VwzyE;:←Ae:zڻ%s)Eu 4)'O+.Fq\G)R&K> 0ԏnz7`iA KۣK7"F+sbd]j})'r"$F'סg 0`k-|tUCR'P;˪Pn7['BGgYW;z,Ȼ&RS.< ξ`ʐ~Jڹܣ,s-4@aY/q1ÆRR{jw ! wJh4LOV;}2W?ëҠ!Ҽ RWkp*٣sɶLԂl:9/w%*0Um/?=Ʀ/|nn5;c~u{@ 1L)< =HL>e.lr|1:h]t"2_$5YXsjL<]1ƛ̈́)pSk]PMUnl+Soל>PXxf\+989tl*0A ]?;ūجF>LcH vm=r4i7BhWQ@/=3?-S]T;vg'8A}M%˞y=mLPS^A &8 ([L!& ̹Y 61d\QP&TQb/k(i&+ כ 싋*ɐ}>-J7vḖB",#DR5EMr-!bû3Nv[ bt'ޞv#14Kfë4糓v0\ls#,z+HG+5BL?Tm4';ԘՒ$C_&ϳC`@Fm̕V*U*< \"+! TrϠ׮SevTRЊaPDGDw)~;W_?bK𯃷V3ANtMDP%/Iƙ*stA()e>ެ |Os Ds/Ops dy#q_RV\ň^}8)X,`19ݽR*zZ0&Kb4ƾ5f@3 '.4 D2!HYs0*͡[$z4nUQ ~tY;eҕbhì,UȣJPPś(bqs_usҵ/;3iIçN{!UL4ܻ@sI IDAT7w6a+,@iGo*3TV hXϨéQPe9a` FlKCk@RF i߰(I:&gs7#?qyKj2&̥/HK((dD0;FFOH ͈$ !sK *vr~>S4/}_NP=uGy}+519Әd7J&)y.nМgTcǘhr3*L)XDr](.[MWziHOT.K)YSK K\z9cG:;n:ŃSOֺW)l)+YgWXb*n9?[K`k?iKү#C^q#O$lLY~ ןc~_BYrckwv7େ13tf~ȜC (oon&Kr9Mb֐ n}z 6u e0lnvEoҰ_0*|'(rFFkMTb?P9 §xeaVR窆gq8؛~dwr8vsg8jPāeY>JV%3dnљU&)h"R`S e\k)VhXh&{B`Lx'G,vK#H2}K<'=Gݽ+cD|Ӻq&y LoɂVŸ{#6ጻNSs)M&$ K+ b0v/ C}k($aq3 1S\4\phn;iIJRYZ::)G~lg *<ל)_wo,i8~©;;ؐuf}}L<:mI> <'8Jřpp:'9Ԙ5`O m X6so^w;3Ks<}9bX Zul?Z?]7nƉm¨osY5cS. T̋4(J4D ];_VUcaJ7BJKXTusbN ] g7,n%%mnU#޵y4WqZчK 1&K`׆pw臶7cx ]c$i!85ʂ@uUnߙv}ba6.2$Ѵ" 7NSPj0~dFj+Mm8:G[hyZe W/ÏW/Y,ќt> uD%<|elؘXOC6crpNAPuDAWnKCܯV +y ˀ ׵_7O~L\x SaEmܾ#?V a-c.p5'M{e%c/gr~G am]fiIƙaMfn n8oPA b;_\P=~c߃ [qq7-jheXOT+F&\=]t60VBsNsoRwkS@z ,Sp-R8dV*xy$Cf%*J32y#"IhHK"0cGĊr/Z^032 vةc`X5Xj,t+OgODEaV؜9ެ(-Z㡖Y-<8b .^a`adVp57%Tx(4pk90&QE%> `-v׻fU}C 'Rw 9/u(q .P"C/B! U x MkŊ:cabXZ`Z(F1 Ō[3*k('BgWv`Q*(˜Rت1vE+l6i5#{{PKjWDV&&)á;|FDU"̎輓[RRuy t* ta`cK6UJS~5 .NBjQ‹%)#&p %D7lŝ;`CIn?~2l@4p)u)R[k}Q9Ub;'(o6\]VJZl0rtc$&&؄g)ȀV= w d"hbҎ}|& (aRw o 8c(E{FWkE8TP(l(I@}l$" $MYJP II{PdaJ$Ή"M6NaoPF^zQɗNThن>.K{ (k Ss=9xE!XLy/-:+=ݤ^aNNq$&~8F*YQs~nND7,+!#g9#deds)bcD5h@c ;Fxo ClڱZ͗"(/A%+y墈g6yW~{,/RП=-6AxuE3+4FXjzkDb'd$!v^wE엠y,Z1`{πbc0Gj2qJϛ^_ "#iKӼ"#ZN9@_,+M%7+FU)a '{r, C@#7E_yW>(` ̧{Ն + 6[J/~FT(|RQUD?7x9n+i2nr Hr+"W{I?w1s8JlҗŖh~ r%}VЗ$ՖEL/A!^a[!\29A{Sc@5y4cx(x&5_j, ӏnaq5DVOZ#+ɇS&?̘-I|@JZ%aPwzmfwY 8&uaC_RVh|pPg%N w}o-F/<1f}|zҌU&>XxANfZYY/,[}gvaB3[ϺEHu|Ȅ$0,[aF,z*,lFY&mEPmN;yNZkp%uhL[C*5Y[ZJߏ~ oa2,Ұɉ/PW~ִ 3d†)^,A\HI^ۢdOG_7~he5/!M"B1Έ> 5`(c ]6^ [ m;.a{r6jʾCs|&0l7 ƨX:tO"uxSquewxz@+/m/k.Qշ8% U> 0nӏ#/c}}͐_VIsRߙh=N~GdQW.UKlIFXxxp8{py` }p21n %ҭK Ϡ#C^8T|NJFz1B2DD RX1ꕣa(֬ZKFxEkikmC[q𧍛ykיMIܟ9*l>MN΋3 &aMF/0T$PrvQ~/ &UvPIa b/jUzP_,+!1Wቇ]wZ>l~} ~qݟp]t,+J0ƂA`V)/v`S^`tV6:bue8|5xa{`UKǿ?M0JABp|%Ĕ> #D0lK+L+G>~S ޜ6/&wl<$l?cx\[rz̾8=j@7ܱ_ѵ{`,|zI> P"Dᠠc r`&2rdvq."!{]ӎyƥ}=돀Bu^gV 1H$ (E]Q_DWacw|LӋo SWy''UcDK T96fku:ðNwUxY3㲟݀oi[3G~nA lŌ"(^ʰ$p8󄃱=>C3rcq [njSH.d̪r_j@\ǡ70m̋C;o bʍ'Ta.8>%v|^Q)N:zCk3I?6|;m]\y5:j9b0?%e ?}1~G|[Wc['OPGJ!ʀu(D` h>utF\-=N|%tÿS5Ҵv*τN,VqHmPk@A,Puz FG=Lsn8͟\0ր.(c`BYā~~$~2=7>=qa{|7I2+]X;|֕9_ OH)(6.1φzLx姯lmyAx*CpAT{ B 'O\:wxz34 pˊ{?@P2 ̝W-[ztFq245?xHiU̯4~H|+ӝSr#WБx|䁝/yYۆ=D{~à&#e`D](X_G`q#ჯx2-)}NQ=dv+G,R0X3)X,mڳCVx{aNqW"Hwκ318xB:_{_TilZgNw!:'e/>)7?3@ã#_Sz&ilIu<zyG셿94b4I3N"Iߎe c})PIe5WIY4t6ݰa~o'ZL'82B8/y`C5lq$Z6"fƇ؛8RmH&l9bI9&cwx|#%bD!i iEPM(% md C7֝c(hc{ ZL~AT[_\`n\j|5qOŒEs7(p^زm~/ &5NcrSg$7G펱#@ b >콃P josi06L!9k=` Z?r585'0S' ;klך<~c\iKn :S_4L{P_9/P:H4`M?9 Y}IO^bp_V?d𶳟N}xɇk`D1cw-^汳i{>SD=\?A -ʧE4ig^|АPM}ZM*~ 1(2 lKmX/~2b5켥w_ ?ZKێxK8`ȴonR4QtbD33W Pq@! "d;wu_m"iPOsh%n9u%5'OOu8gZ1eǔ9 IDATSf3B88(MRR AGF":mk ' O?A+'Fz0ЫxN7'NJ%-\vg^|8` lHj pI94PWAq;12331AD"vܖ|_ yʦ%'jNӻ^z2d' b+NVۏ_z˞e[PVLG:~8S&zVu-Գ> a,/ vKO %L.=[4WO_#׺UlAZ)|g˞8[b6+C:-X1(I *: )0pD 3;4*O$ 5?gP&ܑ)?fSm*s1Swl7iViUKY(6 QH)kNjՙMTs9K]/=_m5$Dƽ$]Rpa#-)?@O_86>/-5^6'dTsݨ}= (Et]cu˰v jxʗ,*MY~[maP`/ Kr>y*vh %mtG=X (YF,a XG(l'fG֬+nuRԦ=>dl%ZtD4ř11A! (P5=E@4 BJO7t=7njrnxqvkv';q^{~lڼ˖.N;£N^ >p~&i5+c_q"򝥊spM3/l󇗳 6AqJf/?¶ 62;'{ VXltO4!>ʫq 7|/eKpI/^{}`0iںm  -|띍}?. }~>Gufn;Q lZq![/E؀@!OۺS  h.FFR/e5~NӕW' OFOM[}ǜR6o623Kq/z2J7z'?_Y4@!@^1(YeT\LiyoB%$ȝ`) ) XOg`-ŸH@Vg0;,_:s>ɥxo•@w9>Ó[:G.^\?s@׸q{.tmr ?KG'_ kJö%jނiv1W6QEMi@L;N`>x/BOZ6r$MiVql(ڥS_4tW0<ݔ(\>4 Nq P^GReF"D;&zdLh;{i3F?vZ}%;)_. } UU_]i Tx̴p8)jk'k `?^S38)`[S{%ɘƎ+ 7o}'SٷbRJ<aDt5?~Sju7܂O~}<`/u/Ļg_~?q󧃚|Q[#(hD(j4ebÎi+M- HhW=BWQR7: #VlMG#`Ɗ%s;m\w-֬ vYS^v_/g# VHqqrܿ_oMXK8Telső/AɉrEQ(=*DD ˰ `Ҏ3&ʩ};A&#Ov}I='=1gホ@^?\NDo,$ ip_66x!AAI%j2KdzdF>0<Vw[{}$FP{G774ϛT 7󣡞yu5e">w:T9WOIC .=l 4?(Ch5S@o &/=Iλوj Z-5]>@sLA+K٧mM0{k_9LE6V4%`BLpZs_^ӸO}pu7&W\_觾Xw5l|p@mVo1[єD\]@MN^ǣO|6cX[h\ZŮvϮ./N9utꙊ|} y77.!KFk'fĠTEo"B'Yh~'39nᅭs.DH9Ǻ0v%gU},>y{:'A[DZbܟ is_-=|h4r\mR-=01omquYFP- v",'NxM Td0XD R,:hT< g6\1|?ݟD$`DώPd*nP?Cq_hzg VNnZbr$V.y+W|aS3dJ[AN٧s. OS |puJIe̸΍>gh=gjѾ{NAk(i=v];D)çMۺJ̿pSHUƾ;q#|[)jZ,WG߿oJN;;' :12#9,c{:5z:JOa($cƚǸOI3< 6͌PCDPav{@H b^K5"u/[/x)Ǯkܧ4q2mv rIJ8#*Ox>ntaE_Z@X 1 @*NoA;ɱi6t]t]y^sI<'I{ҁ' ~hdwz~H|{7Ft;e1?[dmIHAs˃_ռ (ta AK;H9?Fall /)=cd,Zˈ; >:MIy؍p¢鹊~5AۻN['}MqViI%6 柫fГp4~g~ ar?ci驎LD8W?{>y]W?{>k i:ko{ @?Z3?c aZpBjJ@OdG=G|HxsRmœ E"S$]m#7Q"NQוY=˲ʲsV._z|.? `< -r0.jwNn= bƉ09zG{?{>؄YKQ~FkvZzr #X@( 0ki ~*yqInk1f]^n=az->  B3O cjWv#[M˹`pǐm'Yh>t`c:wZX(/~rM'd?& ' @R \4 i?Wx۸ҟ{<0 0oH'@{b sJMs P,m:mC˟0r~Hܧuz?u SZf@zC?mo$qI!' E8_ry1\ >ϯY1e|[\~98S}G ICGuA(}PAh`Ʋ6`7L{O}.oSdo-#Uf(MSapչ7&4Cu"dLƣ(Z;)>]Ь_dݦA|kc['%@GzD ~ęG`}2_9R93<{/#>?}w}@MBC!d#s .3xa4mwL۳;ŒZT7q=ע^M vo% =Fm@i{k F;@ {d 0Z<-I2;0K#* Q~o ^IYz+s&A~ [|{]x%kC#` #`8fYB&B}6Cl*Ƣ6boxc|,T*aVa,)g蔕':MsA[8QQzBiHǣX)e_wrfǢeNbcl@,ןC!E ) hÿɅ˅W~`5a,G~  q*ɭg^]<G끀}Gᓎ<3Nx{<+e4Vd5&xTuR_,3efiL4bW0jJ?T/Ïy10!R~$&޺[_ b0u2.̈́9TDV;BE"^H @0[ )Xc'Vas ?NtVY\sc * zdˋsVMXqqs>cOPMGoeB9ݟ́fE@z˙+ 3߮ĭ=H>>Q_桏}/ޭ9q~{Cư~A,)+?ݶp*?=WXC![NeJ}1 }%o²biՂ2l6sZ⤷6Cw2t %WШ~i<#j Vj1Z)@,~ O-|' ~F[)/zqD30K܃e,9$9v3~3fXpJǘ2 ^C B;s `s ~!0-bpxQpwS{#*`3C=^ERphF o[~46ׇRޠ'nя|7(*Sqw~ƞ!H1\5c8-e})VjMLq5}AF/@4A@1{ucoǡo{ߩxQd_/p3Q| z/|6@hqӲv>A'>Z![\|Uρ^XTBa̙dS:M2Cdmuv s &$\~+A';Ύ2NWSFP{&Xu)#'[xWaag V?!~q?\ZsIr3G Hs{e̺YDt!`A@/M@@g `=myχ^mރƑ싓|; Lh`_U<='(ɺMW^E=e+ϑ|FA0P,s֕KS/$/(sЍ_g=(z~qS3E|D {o@ @C$8d=q!:bkq31-xQee/Ó+㩕QKنV|^@ov?/6h+tZ2pR"ʯn[ &|o pte\p_4o^ߍ)A@i !GQaA CŒXu0v}vTL{tu$ΪSSoޡxk)ꬢ "fgª}Xa߂ }CNB6(VvWpO2e|اD 'd*u;d/ 3ͺEDtf[|5`   ; cs@ EyR@Yj2Nxi1@Ivϥb+S@FAqѻ-~K !8웮hz@#"6G O@1Ga_3 Q~ Mʊ)l(a{Pu4RFa}xFIeI%m*T%<3IPa{ :*i=N@W7&F*> YqPw#Ǚ|Io0qQuZȮT+?_Π13/!a<b{p@@1aA }#%&J@ Δd='2ḷ.6|8c{ι&IƴRJmJ+ |/(?Y(?k9Ēa$dp(]z%頿&#G̭@Gngm A-"\O) EA=a xHZ0mF@[];Rz?^&a%ZٕL^X)2ai ́(cwD3s#v@[]ʯ|\wr(U8(% UnJ @,$†{F@]hfG?םȱȮ&1uD1a.͸TA7LX3\ q8r [OGߵށW]~u |+) {U3Lnތqun vWJJÂP/v+5ȓGD5Q+A'Hժ|m u)U!}1 te_{K# Eϑ/8YRQ~&C_ۃ ঞ҂/AHxdxk`G!\!~m=[,BVi טH5kT0&`θ]]r|c`h70.EK `W܍\WQi)gUIsYjdBo"'9(y9@xSQdtH*T^hr5,Ķ*VonfecQ3(gٻ J{/]YS~OY0R)*'fʎ0msf8 W&qfo:w{ûnAVDoA@8Zl"iu%#%0@801 Oh0]c<;W@΃[?7(wSE&@X|@Sq3 ,[|-s^Z4Tb̹`BUyM8nꙹ]%<(ĒsnOpG0xހ .UH]ƼW-t\7C ڪ' j~dT j3m@otx^ďY<&8K߼O_ r} vZ~[V~7!}яRBXZT~o0dBEĜ 3Q^ʽ?ăe˜&)@Q2)M4 wQ`T*0.<- <0go\YFp LŧDe#ieϭ`.yY}o ENœ+*?ܤ ݺiӉϟ@&,_9 { I%@,u/.{=x/@ˈ.W)|e?ze TAș"+o%ƞsn[Wm;?P D=@(PФ!2I/n|64'h-Hz4DC&M'LR=ϞAM*\g)߅VSLd*a C5biq75UzǷD>cDz|߽97] \ઙ $`3Lz3N+  iͰq?|LX&RER;lp Vvw–n.߱5$]XrjlX S\sϸ)e!',?j出pO?9IupG^&=kr1Z%-eqHpHk PR̲|5$vtOyظ6z.d;Xt 4$ ;ݽGn@I ^]g  42nr>ư [3Aȇ-́ RMD>(82a>.ҁo3PwuyPL?z|$I]BƤDkL8kɧ ]t!C 'X:xR1igėIpW<zpHn+4R`PKJM;S Ȼ\"*ottbZ@wNͶl`3Z>=u[Y8-3>S "b=BgrR̪\?.qU}@H[U*q^3W/V?G+`g?tr.p̂"&."!>y-&ހHY[M_-h/`(Zyh JR p;k_r` |_6l[k WW木fc$"5Lʽ}_@m,lEubEh9%ى BI0de0)Fʄ-l 5@ LtB>UT`ߜAF+ٖ0,CcS؟SuS|ƶ+[U\~@{n/~@`PVS|9wȭwr !;}!ѧO V$[A`d`PzK ! $ *]{9Jo-(;xcޣ?}#8a+w\3/@X=+חVvgz/XSbWvI\Z9Z~& F* e9hW\sKBGbc\x/xbxjѥϬ{`\[D⟖|o /Ĺgy? (t@">CnYR~Mݵza/$]ඞsVwVNf` ;-p(*#RL27 [+]_.|OچYmÊt_o}b >6 9<]|kC(`2H'c5gkN~e׏:m|%oeCP-f*å'-,Drb,z?Ln0S!~kl^[Ӎ;TIXjŇ'F}nۆs!\([}oҩ ~ 7̽ŋXv $IDATyegɍtF>~EAןIGns o_ݒblp#:vϭ!chͲ]+£A ?z A;[ !ߧ3-sgsˋ.eU3Oc33^o0pK Ѓpd!69dcB(0#]6;ghs`[u=_OGSl RR^la ,_@#P~*>x ~4;up˕FOd J2sXS`ɯ #AAh!}j' VYtpj/bn5H{Fbz;q=e/cN?os_+ <ކA &i"a5@wPvg+@Ui\&rȃ9t{wѱCkB6d;CPt:1.xݏ]gL y] >熭S]vY_Z%ؕu l|^~5~泘^ 7$!9#B{M0 $+tf톽w{<gF?{Rҁ/|5 IG/M{NʞXjWv9'{r;ۭ%` s뼙?uu9/&{L:fXXœK(`ۊm BVd*0IjLڷ_0V >9c'T*0kAnӧrqyݷa{tۮ|FP/ V_}Oޓ2,;y?0+Hrlt[||Z'g?)}M9A(_@AgBIՎn\~Iw魵 ϡ[gl}׊3> n$aaSP||9n-ga`艩"J񋋉3Cjúo& ^_.)/|C>q81 ) @ 9-oYKPG'A<ئHҡ~{{d0#z(F"/CkD!\9*{"~3zVQBI>TZW|aemf|aD~uMseܡMf~,sn=8 pPB1+r(ttb'_6:z/|l߼bP2 V7 9YKtY* C[(?CCШw?/kp8Y~O?~a?~5N"BET 8鸏NC\T '*xs3Ą%sulSб!8FٴsOoy/y,T:\Ϳ|'u?fY8c( ;C+?‚zJ^wfc ^xs%G0,^^r͒CO{ Vw5{E${7k (V@tyJ52 ;ȁ N mDa$ s-+BV >]f T]u3wC?p]6E9VnyM+7L %s?zVT!dnx]FysOs/k%Ȭ/Cė0,0}c@ خOvIQy]wTw 8V J\?>"i͜(8k'`e Y Y@֨!mƷ/SѼMu0c\x7m~Yw/:w_ wB" SP3_B,3Ν|Rwka}%=`'Q'dScEEs|ihϡ t;$IHO: r~r=&~Y9 ~ vjoۥ<>o Zt@U\h8ꎋ^Xeeq {pqxPg15YdPZ3$.B_<P|KЃ+*$Q!\߽gs pyVR3@d{p$Nv3^C/rDJA5kHҍYWׄY|OUǓkCډZ(Au&}`C ?RL2R&mwl $cyNS8m~ͼ㕉2"C>#:F t+{uy}Qvas /"['@Rv?cwzy~Orpy /0L-wґ_lM0r%ןn pL4>W]h c4i4(DzgÃ{oxrn0*{M2'ʇ,*j}L nzN[K0y~^ gzG#JҡV7ݰ̰Yur̻ke@ {cta6*W}[` 9})cHm8 \n)ړ%Ǝk)wAMz1owc2I kZADp&*]k/.ʗ"3>ͦNPAC9e*SXKmEJPBɞn>CZIw- {׵eGK&sn]ab:)Mv!Ӧ? %2 eC.%-Z Y}{29wAs_V@ɑoao`J[Z-D )=V:Ji a ayO[M0mErƴA٩?-miK[Җ-miK[Җ-miK[Җ-miK[Җ-miK[\?Pnէ6 IENDB`corebird-1.1/assets/32x32/000077500000000000000000000000001260276623600152415ustar00rootroot00000000000000corebird-1.1/assets/32x32/Makefile.am000066400000000000000000000001211260276623600172670ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/32x32/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/32x32/corebird.png000066400000000000000000000036441260276623600175470ustar00rootroot00000000000000PNG  IHDR szzbKGDYIDATXŗyU?s[ 3ΈJJMq[$Vj\J4%T6J k,1JRפ&jT+DDf73o{ί|Gɽ, >i39H_kw}YypWφ#{0NVA"og^pbL"oyah (܀HDO+ ˪:[&Eal憾R+̌YWG͈1cZ U.{icZZcd Rx׽{1Ԇ {/L@˥r xu$IrƽɢNBPU_ʱm\u ΕZ7_͇FiCOO6?ݶ35Q~p`RU{PRV*@1ggGL7iWyibNˎ㋡^#[V,N>JCIA㓄Ǟd4#6813X'̘˚[~uOӎ@6TgRC qD8Jr֜os9?u2ݺT2r]Dd tʎrt.H@eYR@\ YvÂ,tg 5ps9F̾mqg-LDZ_;Ip;{ǟ|ka)Ǟf758#TI5:Vhjiѥpֲٽ_ϕ+V7LWd,:7*UT"jD6nI`>o`{^[ s(x*6Ԣ~U0^V\}NGt\}R$ɄύW^tΌ\3I45|YW/ǫ5 IENDB`corebird-1.1/assets/48x48/000077500000000000000000000000001260276623600152575ustar00rootroot00000000000000corebird-1.1/assets/48x48/Makefile.am000066400000000000000000000001211260276623600173050ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/48x48/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/48x48/corebird.png000066400000000000000000000064121260276623600175610ustar00rootroot00000000000000PNG  IHDR00WbKGD IDAThݙ{u?~{<F"R|EI) #hLVSh\6!fMmmle-](ƢfEeSHPEpa?~93w@BG쳿{ aڹ[L''o5y^Ee5p`nRad@v!:San-4S#OoiAAЎu{n[iB<.-> rMIR2 [_.nDezI/ڰzQ}w+eD " 8DL@*VS{kyY=lpUH*\ExS^@ b1E)-> TU< o}ӅJ-_UJ-0``sDUevtf%ߤ.no'FN(iI0jmWPSteQGjWrK|ֆo;" s] x5H'T1c1*=Q=o>"L<ꙚҸ򃎛WU4Y#ȖLےKBUR~Uq \zUԥΕߗ#YZz2xxw(QjjU30Feu<}\W2ڱ|=nk{R/h|ZDqX>TX0VE D FUMfJfgWְ7ݐ# sô[+"bDZ8Ća2P37'~&\YG=!y  A>`0`,H E+0 -Z[: 57݅ܒb> F?BR˛M-1D0ő*9 WQ$5k \rH \ټf3TY lgQgQu1 c<8$&1&8ROAC6Ѣi‘%ߵI-7/f@U&1 c9{6c =lË[eYx$qHky քs!kGtFL=w{٦{Ե@GLiF bps8Z2)7Nuߴx>,/ʏg&Cyzv;31)k-R>k^~ ),M8ĩvբxds :/:O!l.W@_RI.Y8ffMab y9ι'x3$ȁ* LUmY 2wX”N|_sـk/>$*TD*흝ek:&{*.9-Ǚ'z_)kk9M$7Xѹ.:-s$I9? 8cI:W>^d*$S(f!KUq6bqm.Z#z,^v>y=X}_?2N]^l-+ڪ7qx "v(Z\bimiW{_l&ॗq]|kOo Y/1<2:!/ bwhY.Uz &=ML:)i ( #?~>^zy+mSilHoWw{B+I(Q&el^/Wu3"є&Oj޵450Fx c7M+"JW8[.e cưAnqUqgr\VË΢}a1EY\֑[5~?EXQEAH[{8ps̄^R=sOk?-5B٧/wp9\wa&9՞TJD(ҿ+˷fxÊXf1>6Ckk+7q2\q0-ªj~/Qoo/Nml :%#6#cM"&z\Ѹx>5޽{'u*761uNOOw $@d qX4S`]zTyFK/O38gϞ=X[Hώ'^:7%u {n5;\Z#&I=hTqp붉MP,`J϶fт #"rPU)GؽEK) c?B;tIʣ߿n57erIk0C|?|TE0-)+a!qGa>tNՌs,LK'F-y̩p6Fy0 eތe_e?9S0W  _xY\#^x"$Ѵ{|n,k62"&UuizO",מ\I 7R̶BLZFz^g01$Gcx]ɯ/ݠ'̈́ZɈ!^d[6MF-k< =ydil!6 @<GPܻ{_dMETC/g5r}#-` 4Խ҆g1^Dxb(Ok`aVn?) Ϥ ڪSeLo'x u@r'w]_3R~qR(!{Y?'Mk/>I?jĜ'2sef`raJFʰvmry8*ŀWoJëE/|>?$m%*-;["<؇q⾽lx㺚y6 GIUE%.x{GUMϿb0^Nhjf8d ɿ&WaRHUJwW8PLsю˥hwDvPةB䆷5H9oiO=\V4szcrl[tEJ8l01^oAc5UI@o# swr@C~tS`kذ5V2 ˘r(.H[O*O7V õBlE1bZ`lbL0H ﮖVL8gV6/~^,%Uor3|.K.ua+`>Ҏa4H=l.j K\Z'K,X%\>|PGkl3/Bm\Sd۟_$e*,(Rwx:YRC]kNҳBo״1:BP~&?,z#7҄4>SWr' 9?=;Բ6]̿ T͵~i}pa7mhng $Y2I_Y|!+>In_c^6D5Z>{,_x^cLQ:ˈkf-r]ugqX`8E3DՀw>KȒicO^:owsGQ,7λ 5Wʪc IQ0֟a51Tmy.åkpG/`C&Yk?S]mYv*;|]1WwA/IQd_˗©'N$M$a0y19w}W'\p*耋ʯ~||^`jEE A#9$ZJ5GTbQo%6m\B@:vZL.U<3/HR&eOk0w;Ő˯gܼf б-BvlaLۿE_~<ոÏ϶>{|k>>I3n9cP@!(a;]BdC*S oO!BΛ[^Oxia=m޶ߔ'[![Z)wkmsap Srۥ1b;0Hо"'Saxm^/;`xc^v7>Qcl#眧hfNZ56BGǨ?2 S8!Ee8Fc>(M޲je{.>UO|`sxF06l޼ 87/~F³k:+ߺoptoqG/=66 *UPagPNB|m2<r)1^s9\zعn.as柲{0Is1 {AB=.xؤ\ {]С#~2$ڲ ŘĆ=i:?GuĬȁy&Iv+5@@]Z1H04u9<ق^jY,{i,۷o1TA6mĞ={jF]0rv#HD1X}ǘ9DٖJA Q+D*_8F〙~_^۽o>B֘V/͛7B C=RͳV%"o8}Ǚ;l*í23FE%ʎє{16m4:edߴJv+% 1hؿaӦM8I"ݭVP~|afLƟy3, rTɄAA0^De CE-g|I&y5 ;(cll;w2447|-@ !8ww~Cy衇MVOԽw͸ɞHS×V>nuR H߂ :ƛ/Z-gp!û,DB= j:^ʤcC4GoZ\sYT5D6nju`p46~.=5.Mq|}n,Ôj|B+w(Rk/׏e {oQ?al{ֽWUw&ݵukF356A71-{C u-A*[|_>XӒ"%*ec|r 7WK.@gw *,#S.__8Byq~FQ=g3u-/e#ϊp9?UWʀ&]|A}XU(vRxXm!(Lp_McJdR꛸m.?(]^4;gpmg$I}I:Z'4˘̄?uk hҹXe=uQuaDÔz7;X0֮IS]e)a-3V*QΘ:WWzM0BIENDB`corebird-1.1/assets/96x96/000077500000000000000000000000001260276623600152655ustar00rootroot00000000000000corebird-1.1/assets/96x96/Makefile.am000066400000000000000000000001211260276623600173130ustar00rootroot00000000000000icondir = $(datarootdir)/icons/hicolor/96x96/apps/ dist_icon_DATA = corebird.png corebird-1.1/assets/96x96/corebird.png000066400000000000000000000223611260276623600175700ustar00rootroot00000000000000PNG  IHDR``w8bKGD IDATx}yEWg,$$ $@Ax(\0@ zzeыׅwE@ U* -EDP\XB$!d]{Tu>gΙ%3|''}N/U_o7Xnn/is:U:W^>+otz JpYR.<oʮ7ÀK=OKkmCLTfRq?tm"ghGʡ2k=3dLLR))M.'^Au@R@@D`fFVC0kdsWgsJuso>:IK^YRy^iﻺR~YCרK:"IAH{%媯N-;KVM A$jeY;_kXØOtִ]YKSbDڃ#~w /)lͩ;|~RL@DJ @ f  D.F* ҉j0! eH<k/K~*?ޡ2z^My⡬~i[Lnecbx2,[$eRǑ[ǥ3?}( B:!r Yr5 Ǎ+jbRkn,!@lԾ^_|a'u:ә%aȇHAhkB&߰rbO $o Akj5DR$ɸpYmJ ۉ;}? aa>S|_ |>GJ;ku`fJUJ=WuzQ@{5UWĈF_ \GԭP, P9ہf,ܖ+g*Ushe 2}! oD|4A@jTUT!Ff Ap\iυ9 lp\|>2*ud)1A< ocF͘K[$<"J?5A.rY+QrWjZ3j2 A5B$9p] PPJCJ Ly(W}7|[{VDLb&۟1\Q`AdfAFPEǸ,H$jT_(Ñ Ǒ ޔPB hB 0`6@H\B!@1PJMc05 uSm:a!3\nEl'ҘAR$z9p5 ed=C$Jf! ePA¸qy#ufWL~d2)d3UٸN^TrY[)W|s-з ~Y*=S3m~"J*0R ~'2z{ɬ!9iȑfܝjq : ^N G8Tx`xȤnǑhkˠ="Bb1D . 1!4iP.UP,Vฃ`v A| ``5.ݤөL-`+ޞ5D(Wx6XkQ)UJHy.4r r 2)$2BƀR )ϥ"Tc lxzF@ $DΠR"P.Wѽ\R t N""XEIW3zPdsi^l|H90P.Q)R&@3ўHhQR (>dO'r{#+"L+/+عr519`$Ra 9d2^M4l6m\(۱1ɺh #QfM+WS$?pҍUU/4c?) :E|.AJ5JLtBc\4k6@|T1i" @6,, `rzq~m 6μ:< )%\Asg0~|)E#CVB֌|>@f  5aXt <+~+hpMO}]o` )G)aR;޹',"췳|H\,fF!ߖ,Ki\DWO`J Bu:NbBD8=gk)`}{Id˕yw䊸'OoA!H!Ǭ",V&& A8jti2A6Lilȧ1C 1X)?Fx#|"߯`c(h"دP[ %_xԹ ZK .!^abClleQD mף]jI~x_zߏ]b#>r%O" Pw>,[Gժگ$'}LZѦDi M2)N9xθdЛvHd6>$Ҍ`I/<c OoCH)`fy\ږ;!&T}CF: S i"jq{̐f]h#*$BA(;% sQF߈R&,KQ'gL`8 `Sp̀>`PX's,ok0ѤH9T{DDO Am`(l `@WY_5E*aE29Ƣ~ {{穿Z8 fn"5X+VZAC'( @p]GJ$ AR@ ; K5byZV9Jcͦ/QjĂi\7X%B XY7!C*J˚`g}1]FOBI kvHA',2Qk;6m\Et&"Ylp? ^Vඡ2X #i-P @JYdDa @Bi,Y$LBb 6и82bVD*FawQ@M(MN +gu ,PjH[>3$#UߚX 3#ڣ8,tzc7’[P t ! eXR!08|xJax~ $#E$o"k1ARᲶb0t X&+dCĻD3d*1NżĴICPCcw"$yp}ys /:<|]a0ȥq'BZP*j¦hD`;":{&lhs{aIU̟1 W,x6;}4|CsV|jޱ8dƞcϕ9(;&a<b9#ꞖX'X FV \̋V|qc3!9#: A 9):U- :sFjh ×\ñG. >Ob{U4F S&q{M _[cҎb YrK(-9QT[}B8+oR-{k>j7*4D*4^ @֗%@GjuYώqbK8r1[Ut@C ]6WoQ:sqSVКD7;][wsq>{d|̜h,m>0McYdƆ9tك? C@VUg7S|z =0}jbd[r Gft:mpklJ`d'VmY5R> KfU{u@G<}*$K߄+{+ٮ0c (Jÿ6mَI'҃[ؼu;s/Z 0s8ķ>R&e&bŦB#[@o)b@jm#ը|=߸xu{OϿ8sߖo/JJ|_ gEFp)3`Vq`I a(DƮPfm6eAuBej눎 ʚ1i|~KBX~/L ^CuqC׶MzJ :EԷ(-| q D$cBf%F.lp[êӰOE?OuN73>weݏ^|ހ1<-;"EPh)@ +;Vݩ Y3:t/tͤ1yS<Ԁs\CMinD hmH|"hX,V2@k]J`b6pM JY%  k_79MK^Zθ=3]ۻQ,֔oG~W'yp!&a [`qd$4"[_&.7k)qQj9F7i+|.Bx-sD:U_DW?=; }ߌ-4&I!f fm6$RG~!(k, o?jx>g< uaoˇ=I(MY_)1\`2¦0Ԇfm6%_8 C:h=0EdFopG ty`"r[>,!suZPGK`fJfenQH Nֵ`Z[IkкfX a3# zl2T*;sf'ZVXe+/±G.粸Áb %+"NBh'#( m~QFJ Lk /虸?3\? f2) "»9]{Ν{lfP$1gZ'4@cm9ι1xQ- ҈54+pB):e|9hK1fΜ +_{b锇-FT},_̌)'b䉻ԇj+B]fx8^ r%C+ Qѳ_=i^m8AWC9[ќɦJE&$s tuuajWH p!M#۷=d (dӾ)j ?j% $Ob[Q9ABAoo/ ¨FBP@ww7@{!XQ[Aa (̐j;JSkE59V$AqFM B7bӦMVc~ذ=jt ILԊ +t ϶zǠ~`l!3LI4B8_6 c b, C[26{PV=c֯_O2Q{&)le 0Ѡɹ`awGد7"-V w}B:(JXv-`m VQϟ\=Ht,Xu-J)]6tp˽KD##!2s RN8h3>:WaA9.z!~ە !P*fM]"CBPx;l1Y&8s[P~##'xR?2Ii' Hئk+AzC !S^mS)) !"ܴb8ahN!UiT> ۆGX| վ|F)m۶,!$ZE ID˔ lF)!NkR;w"} FZE_o֝7nVPyw8R R ]]]شiS!%n|]xprl]tjeLV1l8lfW~}d:" gY69K:LbkcrG ; d B8cLx:)<=.FP0Hi40 [*%{Cw!pF>[ߺVqˋA#a&#"|68"ԈX/B:a",~jj]tUwP;ic@2=FRPQ n ܓ_sZSg3v5>Yz3Efx䕍6*eIBz*"D\gJXU}V̀2-n~[F_d}YF͔q^Tf}sCM1p7!,mi\Bn@ԊiEM@ Z2AzT^*/(9ci8nKwGpR. ` TtMO^:R|R =Wq5zT"%#JF[)c8.7'mDz}01P8">;Bp t>d2QEA[}tŸ;[(3L3Z HMr°"aWxn ᮥM<\;&].#D Rƨr=n5} iYlsDՀ&}$j>sm$&B@h 'E1!.V֗fSnzet^21ӥ"8 0 9de94 l+& N(`"EBk|tW6, (Iųhe~@^#ɘ=a'@ҁt?[z1{wnEX<ܘOl!6EDkh&Y\3 G]\s_ypv۲V/uuЈ>df6*]g="8ѣª#,wðPG$.RM!J2Ð,黖d1n{>S/!"͡aE|5׆.up[X#jX[ gf$N |FHl웊{g Xpۦ|Ug=OW|[6EaT^Ah[MrX|&|#Zbu*zq7G4E\&" qﮀyd=4*Vc&*02e?VDS=}No>{vHOߵH 9g1,OcE}"p~ng 68 ^{Y4}&MOlb k&DGK~ūN<`eݿ/}Ч ԡ[^Hb QDHuG(m^ >o?m5]`gi!9ShtNJ0 9g=x߶&n "xyBOZ߯ u bsn;oU!HqSQ=@X3PZr(-Чƭ/sVPB r@4<plZxNk]20X[xwzGd`ў o1AkO"H2/B3!47*|&/J,cL\HEv h˟^: = LK{bd R؆ͽpĤ֧%|'^rqjj$&L !.zWz⮦%Dް:Ζ:>W0)J|8 q 0DZS9Ȳs;>;_=5Ao]SwM/Ň1$);1GZ}fhSh}B$>xu,!Z߱!gc3ٮOvQ@X&L*%)?jȨ @A y7MI$srIlb-O `'~]+XIϗ=Yì+^Ȱ]Z.9O;O>tk?=_IENDB`corebird-1.1/assets/Makefile.am000066400000000000000000000001471260276623600165160ustar00rootroot00000000000000iconprefix=$(datarootdir)/icons/hicolor/ SUBDIRS = 256x256 128x128 96x96 64x64 48x48 32x32 24x24 16x16 corebird-1.1/assets/corebird.svg000066400000000000000000001123151260276623600167750ustar00rootroot00000000000000 image/svg+xml corebird-1.1/assets/no_avatar.png000066400000000000000000000044371260276623600171500ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs@tEXtSoftwarewww.inkscape.org<IDATh՚]UWܙ'BR'Ҧ5%hh1WM4>߬5VbLD0 -tܽ|_ks3&g{n>) `?&c0ڝ6`<`w6ꑩ Lj F@(񨓔f EwP*Xp ג*_qb)rzDLFAB 9muqXaʖN7D$x ŀ~Ί\:_k aEMP+]I\'Љ\y˽NPwrq Jr `p)V2" EHq\IaœM]mBATQJTt.AWhd-<Qgw9)E~HJA#> :bhA"TT/-<{ӘRW?#EP [{ygϾvնųL9鿿T}J# Rߺp_a]yfTz}z~v*S|Q-!@>WK/UB.*R07bSo7({;bARemQ K߻t~zzl5)]]MFn#)u5r Vb(|VQj/0q#w7M^tZbc_;܌$Z_5]ٲ3}-B\;F l{?Y?n} @6VIB(ϰZÎ+YKwXIbw`=;w? ~ k.-F~f&8vWlC o̤Y+'d!I"ž}ށ6w6})|v3w,/rkfd1e0 C2h0;53?&ӓ۸kL+/-Oͤ=,VZ㾇P]֙L2e"f2i[V׿9&g?|)ZWit7YFnv7Æ-i7. ܯ[ek^l"ʯaZ6nc۽ԲԿ/mu|- NXh1]F/'7"vT:nWH DJHu%/@&"` #wֳa(dGt%$|ձY67L|L`v#?/o]#%$PFFrM +X_$X.T51gIfU֏O܌қ Ϋ( Yz$V˂մ5^~#ʵr&ҞX;h8ՊQIENDB`corebird-1.1/assets/no_avatar.svg000066400000000000000000000120601260276623600171520ustar00rootroot00000000000000 image/svg+xml corebird-1.1/assets/no_banner.png000066400000000000000000001361751260276623600171440ustar00rootroot00000000000000PNG  IHDR@Z]bKGD pHYs  tIME 51־iTXtCommentCreated with GIMPd.e IDATx}]z:pfTL,ׯ+: 5(l0f{5wM([ _^Ϣ${䔓p=5ͳ"i|d;I?91iǟ6cG`*0̀'u^~CM^ OWNc1}vK?훫˵43G5s>_LKyv~pm">b::!2A \ɨ)GZ%b'Y̠Q#V9Rʱ[@TۑʹOg7G2=)SyѠyTll`ٙΪǯԅ n)Ҥz[ e/! Vú LKp^0.AT(fL>Nfv'M6: CHf 굡cߘJӞ.#]0s~K:g / w%t 3~vw:˃<L^pq x䊧$҈f 07N0#W..aчBNR%jw41 pabc׋_'gdVcF'G 6R7 ;J64ns\߀#5,0(< CIi.Fގ1G'rdFLg4WQ8OY f/+9ǚ`>chuOs~d 4xV]dn|y{0΋q⃃A9yr_׬nq |K8eazrDcWF<҉5p295~e)ZGՕ:cQ b3{ɚhtꓰS$!6AheUlQgSݜX'|%ҙzZ2ۋ)jVb(%MeBĀ :cWE52w Ug9bT zt}Yx%&U - nk7pMҬj[49Պ/rZrJ*AX&쿏RXϕ5Θ9W^k@v|{0[%Ta 8ʳZ5ףrY_\[nqIҞ L,~*u_Gο@xɀ:x1^W H8/niKC{]HRMZM%8]zj5~xU*2Qsm7x.[ y_NS&sQ6ֺK2tmb?m6m3)t*\cmUK5ҹ8sjR3IZN&d܃20 @+10 ]z9^ uTm 56ֳ_Zg I /`Lkz&pHgr%'8NGvrM:1U\~]̊[l\:>s8?Z$\Ift`T(\}"k{t^Voҝj6f'b8RgW#leHء}fU;ߊ1}\ՠN2ggAy쐢;"VSjBu{dq {$=dL\W̝/X̀X2l&;D8-Cc~ii8, ȈV/}$eT;Nwb} Og2bܡգו2/LgF_NsH8j>? W-j\93^ǾG= .I<5b.O:)^F;_XΗIa\ e]S@(R,tW x@g4|ԀuS"ZdQWAĨxKu{Ew7LTonڟ_0u3f~J(|SVfuqF,irP[:`pm@Y4@ՠD ˃y?U4sz}s̙<ɱ~cܧ37$!= ;[;8j8-ک*o:t>σ طֽ!]5%FK)5Hwv ]zIt&i0f^RS1um݊iS0 w1hu!-G˲`7ߟ0{Q^ Qxn7U:6\[ U ,eEl3t525h#lf}HXzImߨj5u'=+37]<9ヱ|E]Tk$&'{k^#q46w0yԘ0; b]\+XY\s%GVrVn2Qf?(GJ(xK5#2_Lh+FZ65NT;>EjMq؞fL[PMz-?7/NIsŅH3ltxa8+ۑ YOLwQ࣡vOzUQn)0)*)6Rlw>Ǝ%4ft4=h {3ɥGlVҌ5B{tu>wrV18ŭp,*>ی|>#0V~kw}`2]Y%ԌMb}ǩT16{p}AE_Sl=3+k4-`*`(MF$&19[zB&#ZtU=ix"M`m9!{FuqU1Rmv.RslzfE-y,@4r:w?h3*!޵`ö6W$ <8]6y{/]r[ zO緌?unN8 Lk6^OJpқo/LUw&D5ILn4U!ؙ8 fz]WAp-ֺ:)iȌ``!ZȝDCmUAtXQ-w  WJt1:]yWܩuIuJq}B0bg9~m~L6O'PrBM ԃ>>%]K)(mk|5j4= AWuxp]6nУoۢ ]ԡG͍3|< xLO?>[FM,n_)TS!dbdբ}=%(88 ߸ Q HSUs?" 9jbv*a8{U*сJ#oS+ eAA C;8UL8(| :{ݮ):`3ѱGm8IS`$YoTΜաk3E׹ ̝yΠCH#Pu`A7ߥIwFa;/V+ZГOk/-սN Z榹I[%x ͷVoLbK@M3.hZ.!l`bmO2Z gH`8 ]HM|4Xj }/fsKqw??)~~c^F 9Ƹxq["5`%BY+w .U z P^T4>#կXZM7T#wRvJoUR{pV嘡ղƯoכhQF2{QISTzܲqX"'VpJGŎ쑊c 2EA .ƹ$g&hjͅtahfXC ȕ|dq(\tTW]TRm$ᱟ%`Eu+(jO ZQ燐g ‹N| ٵs}N88?hŃ1i1~^q>.#g^q({|}Gr#@.0ӯAPsA/ф2z=ӗ!jbbdQoƌ;T*aQZ=,M^OuR`pCM_+}WѸPʗ Ǭ0IVf>AJT'+#;K$'x.kEoaHxze祉pnkW%6>cw\ *^MsjszBfدGxArMa%WJ={9 у}ǽbNW7x(ɗ&|6 'd]ų`j:y!1 =Uj}*qÃE0hazExَ݋6;9bڙR7ʪuU vV%'RvѨvR*2wWW֨$QvGͬ 9]MFk[N޵e\gsfmXr%ϫ _7rL?΂cG8^Zd~;Z<س w}Gs~NŏC <|waS,7utE IDAT( ꦙ"]kS+ 0S= ?ֹ33Mx|#dwLv׷xG,LMuM}.G1:SFRC S$ZįNݥp3R'G2 XҦF܈3G:Br5"Y׸1t?]g5AdY'/7y^KE¿= ]ifn#| +W%u6+ RZ?#èL+?<{oؠ} T0QngDf<=#S^p4G}^?Iǁ7$au$}*>?/D]d£}sf'Љ`)ir&vƈQF۽qCHVix6 rѧa6N ΒhP{amO-cLdKڻ#^BD*l;gjQQzO䊌aM4s ҍҖvpWF0*́Tٷ J1;N `{j)^qU$l}+Fp>ly71,^ç+N@V) fr> uW.XX) Q5w6sdCOFSٛ"XS׀+tVݟҬ g ;@$n3mTZVT=<'Fz6a+إ21I UX'0RHqM{+6D-h14 uV((q)Diaix$t֑DE 9ޤWK+HQJcx\ζ}4q@3xy,ILn>J}NSo"່Gi FC cOEJ8;^?\ʧ뎕(1gPWA&bi#!]dhݢ0G]u^. X3|lCjtWX!*pN>rnDjrdg]&Ci[cɉa6NeB}GxrY*|N.Rt̗hovKJ26 BKf2=mY*~|㥮y \]|= OR Oɨeq4ؓOf!ʟC0V:Fȫwx`&2FcKJƼ>蔛 鍥aX5]*l%PmZY ,<\9OfT$faʹ714hkk@KSMPS/4 bm ;ژGͬ$M.IsnQJFW{nSk'?cJba'nF;5T\micbk`G:L|x:82t~-OviL]wzԆy՜s!17Wo<0{jS0nE#z,ۉ-F*y65h:NuiW6d:wn}iXH" 85Q6`Q>M*Fۼ^LܱZaU nj+T\ͽX% 7.[vyې\bG/3cB*2"hd:P[g)éӭ0Š%i12YfXzHUcN,XUpaoZ),Tyk˪-d1f\ c`cEձˤf Q-+nlzƝO.dU55w%K3hJ(Ot'1ػR6(.U7qC!pn%/ XWn,;S^,h5{n7 d2F3W{ :!2T7Xbo^6HE1?-nc]yy(Ow7ObYՎƿ<#ݭIB`4VJc<ʼmVn)jq|td* *֮B̽Enϊ|1rÛRyHaAg%^7]]ɏ?Im`4i0~cLB# ?諻]l㬒/Nx-||RK惈y}1P(a<=R>.~ǦR<4}&.WƖ#`E+ m%uW֓O}&'0VU.>6~"CNu,WMl9DP/U4 -,h@ӝ9\Ʈ^\;֤$ﭺ(WK`$ÚFF+3Ŏ^ Мvv vGZ$ %lNiճdZ!w&iu-q+>\tE#ܙ JuuԻ~ GdѬy[ ]x٩ ǫwT}qW;ɓdL_Cûݬ++WNo(txc_V5VLt1\{I-6w^=Đ; PTyQMck=XƫX֗i\|){0kf;V43ϵ* їrncHFqU(Fk,;/U|N@ /'F("aZǩ(,EjW1b;;FL8K!+?44IHI,lptLmJԡՕb5c M =.1Gz] 0,7bh".xϛf)jM9N5;\1N>N_8:~V˥L7bN}LB Tncg)F1t܁F,{y;7ؚ䆢T9bĿJSkFNCKI.t)` XMW;27 7NJtJ\(kϢGMZ|+zMb2G7iԀxkf왌w-s]3ܼ.,]<9OAvA<1LhXwi2¬H7WF1FqƄƇh7FcǾWu1h~k_ML[`D•ϡ꿛U W& z)ЀD!9L+Bp6kJ(;rVUBCS[Q☢@*_Ɨ^mStU!Vޓ&spʥuJH7jfh㨴e mwoGcNwQ,>U|_;B M ̊IC;_A?9!}^o۱4#h5. uOXn="r:^ERoQ5Ɍ bz,9!ݰpt&Տiй!U.h3 si92iyp)-rxg1HF(S6ed'4Bhn؅S\\ۆ˭ht[EXUr'd%vmJN%>QKF ΝWE]<#]w+XW_qW'a <ʼ$r}unw#AcײO.C.{+:-%gN^[`Z#LL養,|Ԫ|\&E+yl0w*`DV|NG+Iд"Q:W׹_ì *]{=-CCe_3~mnUJЕ>W0{UT :R8(ԃU{+bRgFcqV9!'Ƶv>ġrB91PWT>J8b C3W8 9CZ9QҎYh5$ay 9'i,-ߌwEǹ>%=n=ΓjLk oPH#|<}3e#**fD炣E+ΫsүY5ѴqԑhtsqڋVB?W/𾿣_L+>]sg{ؽ4`+ lCVq8y㓓Ef>lS2EW -NC9[c>dO$TAS"`iU>h RU)ZԵx-/>O㮏W>;}Gʼ`8U\7WxNtG RaNhY~T{ΑA%",bR]zC )l^+K7B3y1jS7bIEPYܱPw1lxFceڹ7ZSSJ|Mڭ N5&7ՙg/vDISRdsOjpE^Ie\P9Eqɂ#gRuCoư"Ci-}YXM7D; ȴbE R)g}vfѫA>8}x&/MrgNDsX ,b݊:ZՏv;K<էӵ$[Ly(8$VM!Qi*NR,ӄ=<-0F0PE0(p1GL3ɋDKH¿;ն@ =Wp +ިdMCYሺk;VƉFXe)79uzVeZh#ۂ&f=xh-n+ʘ>NV~|TbR,?Q/[pV,^!6Ax| 1y>g #>Șa9-'*}bA'R.YG bi àеw9Z ]_*KgWO$s5ʂ5+ccv0}KWdz~HH%hEVY`E?WFףuґLuk^JoX!fu,X-BM7@KF^jkU2U]̒Ŭ92nB!kX)!c",~ꝥbWZVnwV|̫})#|ܐDr{z-5=[F/= p7=}9逯QɼW"֎ ^jxݍq~hzd ݊`: AQi+Ej(2NVX-y,k8̝}*NOFn7&9'/Μ@1i[,SY -ZHGoC7;*PoTwiP?oFn 24]rX6~nWQ\nq !fS-N EkԬ{6`UEJAS uS9+5YЛcTݻF V~5 Fu.|0ڽG#M|]uފJ˳e߲-Wlcshq i"L'< QW"*f0 wx+ zCx܀NR*8ltZQւ6вHW:0l X JF^%4܈T.(+Ԍ}u=4.DAVoE'JJ7eTsٮW/$=A>c3VQ󌦹欠ɹb%o^wsO CK8U yl#yc0Pϓdw/{~^)>!S;д1xbkt@F\;JpU# 6Zqej,ҝmp7GdOn+ 諿Pn}a&#K6qZw*$*VU1{Lj~9Tk2hi51oq9=VM؃ώ[ęׇARx½~q\Ài…^WJUХD.tmm-6`?Z3VRs+ޠ\̀P 7\?؁Ҥ*l*1K*`;א,|\F#^غs1,tG '_ `J m'^-_銎y7o,FJe56\\- n-bעi( w[o#+rGgnFF.Xzڅ蕖m2+sS[ܐ,c^c?? z7틭J: P~[1LE{Nk?"x z$q(|5d dIMV2Rڞoކ|CZWi%É CVl0Kw;Ӂ|g2)Oh nN;mP>TOr;`^h*vJ\2'E]GGU/S̠SFhۈzs4L'1wvcB;a7o >ײ5v=oFgwgnte>@Ey`b [߱ &@˘b/U~7lfXe1^Ȅ)Wq;n:?{1 - w*&b°lPg#8= C?f=L0Ӡ")(6#))TGq礁%ɣ"nA@$OQXɑB딌XqG_:eKq+@P2=KeI0I q~4Grz/bij Y1ރΙW?5'=s MjuUEr]q!<{NZq '5>s\3.IrqZc6Ct+@7jVؗs&UOW-ici좮j8[8?p5W5tQ0'4KLLq7"Ma,UE)WfS;*3R=xTAhm(x`N%G^J{Gp{R˥xGD=OZ`/}ʭ7ÿ wǵci<_G\̳&%{Gc%yЮ_բE ?KZ7q ?h$-F:\ڔVPy J)*Tiw'(KD `Z.X d1ŷ<6[4`[Nͣ#hЪ @RcæL}Ӛ0Ɔ9 KS w2PI NscjӲn܁FPU/v;enGf -mMRg`dP[e TwCȘt%nGxŻRJug tج*lG}׻xֽVރoł~Gss'WOw-fMN.: > ^N&XlL0"yR/8)0oi]}g Z|qBzm" 9}oV)cE0wbDY9ִهῴ8}2455{Wudpqpې)LS߯t֋@^aQ˯qZh.h+/e3!NG խG@%:bN:#ktjڡ7f2aw8V1y 7KERsSe̩7y3/=^iU^Kߑ BѰ]@fRNWha2 8Sx0I@N aSEIu3ٟ(.azlN3E: u:Pw)PlBv(a5 DKtn24]ϒ=u] 1jְ]O֔pI<盛 ޻(?w8Aqs^`oZ|\a%'^xR wxځ ,jqT Eu㗿Pwd :Ф|m/,X%F{X7f8Z C9ǎ2cFFxYW~c 9anv%ziFF1 :4:;&+GζC5nri#]O>7 t'?K.Opn7둡;K1+1Czw|B%|fa=*GW_fyw^}o~)+q'ME5JJFS57Br^z7iBz![Wk8{!v{qjl=Fs;vf GfF9D1+Uūy+z4F7o Lz8rK @8/ fPrᡘ>*yg_M7`}= ;qj `'1 U;ggΚzsgCE/g3M^%ro\%/Lf#uJ%+&'t1*LnTHά SQc?t*lR׾g Ą^]`?jRgFqW%K^hj%,>:hn*Ia3ғӷbp(QՌR^uQqO=Rp8&5MEل'm--:o6EU+,EׁDFY#,#ecC`{8#}x:_MYavlG+?{߯|X^OΏbjz+AB/Ff.ZqeAroY*rW$ _H<meL|AvB`¤Ċ)[ @k+|Rj2vdU6̦$`F9 cwoiaM5k3\Tm˺ lyaZ65W8 #uQzvZwW6laæFun!b\o1D|ˑ)? " |KzO;|yy\tN^ߢ*^hᙉ:jf$!Jϵ^5_ #T2o:Au*Gd.9!ogߨhWNS =5OWۮ v՜x U2VӮ@#" ovx*QML(4f\,{en NxJzt_ze#}(6Cr3 GQ lLYR/gbn3љzCe`pNnuBw>mXz$̖c i7MzuQP {\h wFABsfaiY5&uوw4قHfڒ`jGt)-(oKLkJ"v6tr/IJpp'brs1RBTw]ҬaMw闎^LcxG4!zTUWǦN»-R Z@gfj kc8W=[w `8GD |;cnj 1۱8|4a y ^ QO*D#I5wLoe;gݫݺANw"gtJpO '0_>@Πy B*uSԙW`ht[lxzcE516}M+b-GLlѰA+#+n̸ UHW ƟfzC%%NL=9B'_`̌Sh2ȷR鈦{Rǡ]/W?ϕPhx,R3mlfukϩxLW\W*5xHc}n>mϏHq|5qz<5FxI5HXLZ kAZ*!-Yy7~cT@_,Sx FdP2Ż ?:4}ܗݘ4;et1kkv`5;eRQm7(_즧1wCqw^)6F8T}nsUfȵ,JAb}ޢ>AKů:,$z{XT۞)q.*r^R=ǝu"q0w;~SQ8k}x>{gֻ97{y#ܛCG3}]cznv<@x3l"MUHKYUYӳ6@I~*W|0?2"o[fѴR3Dm̬7Vxi1mdV֫iԖ]1znr.^7[}1oY@Xb!foh{l~pAݗXAy ד6x2TM0a -j oIH;KwyY^SѲLؕ=:U$z!,k"yG8Rd+,V\;Nxu{)Bbp]˂r͞J=,GښVU0ȭ0s+Fh۵*ke]."ЍO3l\aM֤v[ IkSs5B&u=`XQf}NQ\{+Mq^4o5WNgwq{\7?w?gpteU010-cG+U4)V7](oʁ"\=Ą;Dw3-*6MvNOԗesEzyU) 7UQP@1:E{N9nƫP&yJ|9;Yvi:e2'ť?Kw+x88l8bz-1b6DD*۾^&f?@/F:%ھjGǪ*Ua3Y7]~oXwM0~0x?yf<{Zlh{_+Ν'uz  {'8g.6YQQKx{&197aR}Q#s7e ajMGIB7QY8Hi0c]3?~βs[Bh쟌nRVXCF>qTm|~p.)B^ (9ƩdbR'~00k'Th8hܝ.3̕rF-SشOT`b˙mY;as 20asf?T)ď?\[c̆j/&Rԭl߉ֽփW}>MQLD ]t!֠Z΃=<2!D<}s tV]ߋ[QS]@DndcvZ}Ao?FIHG f2JȂE0 1mӤF]k}F u5 Ol`tO:sqa WArEF*ē:DP/[5H2=+D)9e?24M")񂅩݆-͑%$] " ldI MVoIjfY8mZ6ٿvsa,w{8-}={or9e;௜Z:G&+i.q ,s-l}]!! 7=U0;wɠvk޵A6瀘%P.!gk x$7RzJ e&(mN q\X|&a&g2rZ&2Xk-0tF4l< w&%#=Q==F.dݴCk~_H܄FƾkiN0/)9%,23L.;vZ-K~wW\kio W,myh.so}E[}i=EL"0uh0yPM`H1 _ |sq"F",׊)YEwm*hUmIgePC=;D߹.0J%0ܦm0Jұ́iAkׂ]VwX*g5T(})~M  q% rt3M#Ŧyk%4'w#PQ2[ᛡ+?备Y~ V8Gy )|NG/gFE~u󴽁&+gw{9,ŋ Z .Řr./b"l-5$œ/7,Z.*jS9U,CXq!שEQ*ck<);]BhQ*VHmˈl"gՓMqt喣>RМ?[tn+ifJkK3%#BX=pN]#k*JD=;i{˷ IDATN W2| fkh,oDgvҕ$@WM>7'I|+x ~l/ݘsx]s&mP;8;-5KjeZ10Thꀤ/"E[0kI@G=f)h ,ocFna4@uiD`>.+n›޴7TKܳ3f[FIBw6l`E6i$q^97IdDiHmBrA5hZ'HCi`/}[5g+]q|-%W;oyw4)`œXFaA?qpOCQʔ C@_ک9 0z41}5ʌPL _^?m5"SV X%fn?DC']+K\q#uLU1st//pAfZuWʨ:/( _te+Jvgv0w&7!`Aކ0>{B <*:<;_-<l~i 0b@Nnx(mȈIؔqj?=1;*Xh3Mr]Ahwz!ת;'T?Te(Wݱ6#jo=h9v(]oe= ;Ge? ]jYyHwXhˌ Ԣ1;e8h,m2\Ls.^5UtBkNq,/ ʫ}$ھo1=>y ⽮_Vn+>r'9uMk@xRaR|Pun]L?p9K3&x7LvzfJ;`Jߞ3sJ&n;'tY=ubWߌ3cϿ =3,x?f?x68AE"fTϙo pKY㞔"/R3h_ @DɵLyyYyՄz_x3)N%c9 O<GSSdu5p;x$4%'$W^q r33FA}mCnc,Ǽ0U?%Tׅ]B!*NG-Ϩ9\<;+O ^;k4|0}gں6{!vȭťu^+:s|zW3υ4q~1<r]'#ݺ[˛~hcc f Ӭ@T4:~WvJ1Yզk_ PI8dbZi6tl5bQ$NhԽMf 3![8c^]EdZ:-*ΣO+2ə c$ s1^²|'u%HP,}猔vw 0elZ\+M Zߚ~»:{G_̟{ޘ҃3mr ǁKpu|*"8݇;$̫ey0 fzESzBEL&hHŨ4_n,>)gAT/SGKޭ:uw)fV?ٲnr+D-A3Uc[WW{=7f4Ox@uo5+SmRJZɯﴤaqI°{951G\XԚmnP$62:{E1NjNaHvqR.GXfʟS}G|Z\ܬNø*āJV.Meu,{9r?c~4Sf&n`?8~|D+ bLCC\ !O _lW$VkA1Cg ?9,3)5 "Um;"bOJX9$!gƍ[C{LPh0pȯ4x1agg0L"4 h I4^Q%>swƾuV+M.^hmG!7lm-:9|jW ɮ_iƢX1w+3{8`tW+> :Ou5~ѲUtƁcNJދ@#{~a Apy۞r0WCwG6\ePF!.f>s׳O3#:jT]Z= 0'R&9Nkf5? n39('98\ņo?1;b\l.̮v.4U:vr;͟ \)sRq9c6C&YlIuXBs!V FϟFN@!7k3jr_pϙ[˵})}7[9Sa|cxuOZ+3ᓿ1*c~Oܨxܤ6G?A*; ˫GHEK?B珍sm@$AL t -&&p== ͊Gp Ih6j!T 6•jÅƐ؜ R]{fP.).ZHNÐ 7.uZRri cTG'wȾJv+ⳛhMQͣ Y5n P&)rԉ;&TB p sv׸_Y'^m3)8o :a>oxtb{OZ|ѕ~6ɽVRO0 bcZV5ROLA #W+ޯ7b_'u$E`@0Gq7j>c>[D-*az(mI8c\.l] dSiBG,]&iަqrZ<mKr lQƵ{]jZߊ^XwR(oc`+xQKOIѣqu?Q4.i|zE"T:Q<~ iMK&2ɾ#go~fv]9vCM;F1xNA9qSW*H`Rr 5jNJ)Lw/F"Xu` o%IFLI).oiev.CjfFa(ugG،]O6H;zB40 0pĊL[,:# VffC-*7&7uM75( Mt2.heH=_{3gETʬ~?.$k`!;zwjT(z}^9=w+zUqzrEyuI-k#Ճ='6a)i4Lڭ6F˖K,S*挋1CqVLDNJډS)AQQw݈ R/ => k3>F.#Fbn6s % aDnv\4ٟ 6lgAN'mU7 @K;01&صi̓|K3L'3\*$ɤFTOԮ{)YSHF%Rudɡsc!:ss}-~7{f_D{3>9m?.F{M t/yg73F. J-nô4%d:e{(q4fr]B[kURһ.k2ě7* %]4](|KY17{p5n}Vqu۷84y}Kt'\"w&ߝ?Uf:mԪwD߰c=q[f8k+)ܠOfތskG;Uߒ;Wu?-[.aqY?wD hmj>D wEox'w9oXc}oww`oMl]^[7+`f4Dsލg4P\q7L]z l'uYqO 2gKB/fI{4T+"TPD̺EC͂dó*H?N)XTmRcӇdU=CW=uݮB}w{Ec}6n/=nqo\(qyr ̴tLϧ8!t[z4ۢKJW8q&;Pjaf +juWXzdW!V@*e8:5b\\ WVi*GhS\ly5 9O$5Ä*k` M-dh΁ԫew$T= ;9_mּTBeK[9S/>vfqn]}^./5d|4S;VXk}CZF%84gݞd]KoC+Q@/'bnA`s.ڼM0U̪>'Ph~d^bpb屋ȃ9opIhPax~Ek0yd).+8rd 4:鷔`4+/c ͯHW:鴎ANߗ|̈́%"OR^Ԫ6 [o⓳"ѠOI၍FdpNCDɆlH7Eg{9ln߮'MFj4:]x+-׷z#B g}WH8^Yii=lx%<k8Z/CGW+14_O4۲ꢊAL6չn|<ϘVc6?U1@ah[yef8ZDi0\w?1]k7Ϟpk(Ӥ͂>s/z6&}s ?7!F+",ȣOߠʩ .Dq!h[eSaH>FRmT)lHӅx ?9>w} 6 ⚌ݯ:K&%'{:Xp'a=o\Ur]On%&@B{d'PT`ٲO_c odXp7̿5`=~.7G#]9߱*O̠EMވ"1V;F;'nkoZU=~1ٽ={ZЖz )B%؆YL~  mVU /v`Fa2ƎVpE1hOx!c/i|eS*]p`:%{.&&@ȘR2/8P^a@ÿ-;ۤaVv OМ8녝S ] ^ppJ ٘^9N{I3WYIìe O\/n^r$_*+z} SKjL.q`ε/fVWFvȬfs@c,DWiD0*mFmk6:qڊ.x ~ ~s]nso4I;_R%yQ{'c3 TuF#O gBJiBLa@0˝LFFክUTZ\/ tL帬 Sx@xLO[6jcj;h s4>^D&IO/Sߗ'՟EU./X7)nnp08jW>]\S]TJ1l|(<&6M2)?A`UX tA,]JB!'"r!"H~PX !@nIaH u qG3@\;}7O64lnWE_ ^4w osg{P^w3xv7Nin(n<Ww31I2iN;(:DEЄem^426*!%>M6ht8Nh6raubh+1UK H(Xڟ՘NdNJUጱʷ4PŽBا_t6[#_\jP@Q&|rN©ApoM10gu$ETyN5Vt9y?xɭJd]F!yܦk6@[4lO-%żڊo7ЀfS><0r"QO Pa{RFŤ.Yv0 URƽ}BTqr=4 ,y؁&/rA)o9+,T>NUط+JVd>bvOͤ9U-4? _#c|H3:"n =88_{ԛEI>V0P^aƉbX=r( GJ纮UW;4dCh/A={28xh [/#v%p6 ¬9۩1SI!kiU}|7]'+a=9{_bazb Dh?$mBȣ,vDE8u*V-ƚw|}6? v@{R |l+*d0>ҴʷBؑQK 'P˕{Y}" xQ;\ҁgwMA_Z%}=O5_3{]kxLJ0ME+p?{r裭i,y3ֲRq<%عh2A#Q-hPd%p"I4FG0STKe9(P5MYZkKQ7k\1 ؼLƯ t[s/sfZ y`*=NHIlW9]Cll=tW:2ė|WLurfx~Lctu} A7];bFn<+ɞzu2->M5Ϫ^4:q[OCt?.B0Akeݟ"ݑ9tѼy1+6K4"ZuQ%">E@/'wL }J_);& m'PY5c|k CQq#^S<].Qr*R|`3Ѥi_Œ @*˯R'=y0{'޲|.AQCv7_beb'ol5:VXY Yێ9yE9Zi Sf,Õ冽 #:c5pƼ~}vv!:}V2/ٟ4b-k?H7;NS2 eS Z4x\s+p0Imc06'xI( - Nwu œ$' XoY@mJAK5^)ci,_UA mB^ +u G xjɤJI2jn>מ .8se8~X)yEod˛yooS@q:ǟc3D)*)Nu^+'퐟uzd×;4B,6Wܫ f^76|8L":􂨶^[?R] 1jdk1'89r7VCWCڊCMcOR"hӂGPsuˣ&S+*e%r{0t[cB23g0`ޮ,&㭯N*IRxook4ci6|ySzƸԠdط?w0hGtGY.+J}+ON ^ {ŧS_"qeg3#b:8cD䒗Pϼj,`3fi"E+dN5<1187ˆH!x)[PBMY>͵+\AScr4x{^>Ql_x:޵#&Hx]mDp5NT3g޽ H֑qcz-\X1 W/ E,YxT*ud_#|d…_W+c?R[+0~YZ K=eF}#LsBkp '@> ̴:JMC;k`5r_k)B73U%WO% AERGwa^6 T|T%VvHTw"+i`Xx]#CtUla&H= DKQe2t99`!dgλ~sEs-d1|'Rya2XKL\K̋]:4qoߜnǻ#,#P|Z!]a0 Vk8n}سAq{F[ _l}NQsp` بy,X PXDg8YZ2;ORiմBi:r\D?UvfJg&DpNO ^bL%B1TX2:1rܼil3w-G ͈St)`wʡ,kc ,7oF5 PpY+SfgU1>2 OsqQQ9qց)1j1F'h"ŏ{A,VVJ|\2KJu]!h| P ١`v`zFwxo F@#,3PzyΙ#& _&GcApߗ$؊Z RlM%5S7xYӡm"JWD 5FRˊK T9#1``N6tYlrŌ5y T*f+XU[XvN2J'kY y%2E&' oB*Wv[0!n٭2sՋS._WvGPUո{Ӝ *-s(4-zSh;'Q7_NbtphqPT:nH*X8QWXWY;Sǂ=JFSO}/ϞKp]=O6Xi0kQ1ǻg5"A) 8O"޵P-ӠsCp"]F.@Fy68Ű.c_3F:w]xуagŌ28ZdD=9H\9tq88 MLF}lM"~HUMuWkG"˚Έ:J_sj5ʠ+ӱ3zV`=~wx9<خSGH P㐅>,z3}SJs},y0fQ t+y#шkŶz_(`Y.&j+]wռP 2³pM"rB&zI!KXgbN~JܖbVrU'6댺kkaANT^7{~ mWY0|m\"¿@ 4 Ԫ]`<V@Ngs*ZT+j00V_ (}ѥ+C7V9n_W!0J;#ş Gei=/chfڇ:jP $\.|9甕3[.}gni TW|l1Eܗ|;¾> q;<>F2ˍ3O>8|SX:TX \2*ܿN+Z)zsuV,i6;C e`SY~/cV/Y7l וpi/;?%Đ^#䝔~Ń26Pܭ9|00B_0(2v}YcTcJR(2@#~!HX]Ъ@T$JsVYϒ*,v]P7UC'zTlk_kq@>Vloސ8b7t [.A6޺lOSa M6ō,:j_1J-ȩ>AZ(Pk?-k$21O5!Џ tEx?jE`o"I5 Jh-#%:af+Fț!/ŌhXU/,E\g_P1B&vA:ک#tfUw(iͼӳ>a=^+/bE#ۏS.x#'"n)i\G;7y [ I?Le(v먍{z q&P &vD{e{d$,QMF}hfTT]QCߧVf]V Uauֺ؍ݴ7ʟjIDATl;ۄ WlHf 8 !W(Y{TS11V###X{&l?o6lpA1Kq \3oe{ Q0 R*V~^X\Y\!OXp;ѣ;87>|TAW6sG Dso\ځߧ#FD(bRGt5FX B?$M3 /B}3T8 n,%& g=)uGd9/-͑@YK2ri\XXLw,{ʨi(HMY1s V(\WsQg+D}ʱǂFw" 01J @b&C{`;lΓ|{|;3Ҹ1>;}TN`yvb`AKNwՒCI'_.0lEpT4Q(:F; VAFacr.>x.Y<-IJx:fxzB:oͰNt7¹Hn"lpqrE9KsIJdsJ?GШ7(ɸx*6ܣd1 `JF`ʲr3{c^*uA^)0)+0͞ ?ep]BG 2\cM>ss|#tq_M 8$Zt WNNO_]ɷ{=n#r{0Doe^.ѥ|uUJ 96kJ/S;?5r(bb>c5R_XA\*,ۀėV[ eVHF?ZqjQf$Nn2 /L{^tc`ĵ/1 [PHshT!0VeY5#3 ?F {әY'k_FJs޷fmw\FJ۩އdB(1/[ k{LD!EBÅ^,>W"-B]8'W2^Vq>"HQa(%]'_YtV4f 8T:=3 %2 ݽӨL<_NRUܹTX'j3O۪`V6wp/# \XC S 妁 ЏKnH*7*2q9|V|f͑S]5SE.Dt*1[/)S_YM85PgckSءC4flISѹ";s}O=ϭAqdĕ3ƬLccfGϟh?fWuOcg_Meü׊^Yi'dA2Qӌ|Iׄ.g~Fer-2\oSM" 㿍ST͹34<&Fce>R q0]sϹY4U/r9GيMZhrFDŽVhѧ~ ){BqS\nF{"(\i<>թY\#ϥ3>* hgt|O-q%ObVMZ<ǽeid46dOpee0QWaЁzhGaN Y]I I=|pQ\ qoƘ2;SsV,C 6N3ES/](3@e3nNsSkW=nG gsmMlNx{t%p>sTS~X.@oZI~܈\L F ҉>n_yՑ|O 0l"~7r-uZ\^a VkXwF d Ҿ"nWZfi7܋>[k,~ϋO7 (5(f5U1}LNQ+KRwPew I %C}]׌}O/&; PUʇV> H72B>1#GR}0G{C6r|=>м*\~pGH[Xs K?%-H cx[|Jw]4ĪE?8e λr$VDB2_6 Ϛgj f7cyjj)\w6\Ia$/ #%]U{#LF3~;YM'7o 2(Yߍgs'<o:Fy{5צḦ́<w/Tϻ(fR~:sLs*'10ptpxXD4[nhy *t$ܠ[ [P#23A܈Pw5We<<8[A($)8yU8~␊R.! Qʑr>FJ@'݄ƌ&{ym]rU[234Q N#h Lpp,f $5R6a{X_&>_Ox ε@?ض" j ymzFՍψ(_/e/?tC^zځ5GO9^q~ߊPBs\njtITpDQ *_WL" 'MH g25ڸoՒ+_[\Po^WU[VY wن ߐ(Ns->u ZSћ[(")(d(zyUu3{(gX}(^(g*VJ种p\b}$تط~wav|l ۜ4{V: Q!Nunqz] ZviI˿ &yldFuxww>sǽ, mF,q{TL$WuX*ژi#B7ǯ{UXS8MRD M1P} ]9QӪ{̽O\}4gEhΚۢ7cdw/Μ ʞKY!g#Twtї\ikj9LeZU:jCi%?%dw?4G֪sQ:͎|@,ё> T5U5=$44U Ϗx&tekV<ʰƱHڏ FP>Qk zAa91tFHT}:ˆVNV B岫 K^:)QWʟ⊁IĪm2UvY|PY kHqpU1Ło̓X6J(/*r4US:3A }]æVxnj_s tEǹp?tn!) Bs{G荙wɟWpMsZ{P+,c>Tօ ϡՊ#L+i @Ǡ(tDʒtoK53 TLSBxFS%dSD( #IzƬ_S@A祏#Ca~r 6(Ϩ{pQnja~ܪhd#w*/"& 18"wڻ8LF D4~*vqur[9I}PEj]swŝlsw`8Zwy:6^tF&x}8w:"96~g4"E%iʣf)#XogFJS0a N[+]Yۄ5&(-l1~|z"Jjh4M.= D c&\{+yMQa*[2hc!U`oQ\ٌvF <+EX(wk-crқ_gmG7 1cxPZl]󳹻Pޘ{e'Ʌ}c:c*9jY,2}*:Y#~)j׭*y/EΨ"}W2#dZMbV}2"EpΎᝩԒ/ =(Flƺp +|fӍtvջCqTBUEǭ[/Oүc8-#B Q/xQ옼!EPۂY(}Ok#NfYbډfAI3U{!{)${@ <-f.+nN01XJSܩ @o=cJ954FE#UD.F4wE#휆YpJ 7Ci#?ձ+q;~~ZgM%@o$ω>}  9y`3~F $XN'VG-[4#GsWR0 ֓^ ..]bxKZ`݊&+r#ј#F#_uT~VSڳq3S[7݆iaMU.dRuj=# 5ZH>ERZ^Q8o켦 gQG74P&9.kZ_H[B63m[1hvpa3 8r(Rvvoit8᰸⣖ ߪ3v]Mk[IENDB`corebird-1.1/assets/play.png000066400000000000000000000021051260276623600161310ustar00rootroot00000000000000PNG  IHDR szzsBIT|d pHYs:tEXtSoftwarewww.inkscape.org<IDATX[lUoY[kZL8uM-ƤӬԤ$-Mkkki)p h@cT$2!R-K^R綻sL.lOa|g_Μ`mC,/,FqPQHw`Yl}4>E^|)T pٳ/:냽EYV#Iw\aspYVt[2i>EQ{p@ c=PfU rW|DS twWUΟqW|ㅧ]zfD0k?-,S9[SL?,Bjvg<[+>BNtw~ɬY]*I+ 7r7!L!(z5K?e9^~qwWPeE9z9ěw };j{HIf^<`JCCSbfiې$* m{R'`(WC$dlHr"tN [UD>EhNy< =p8$ޘJąEШj~$Oq˲ɯvHn4cccf(#H4?j|?m߿ |?6;*?o 5n_s9^ahk4 <w࠿ JIENDB`corebird-1.1/assets/play.svg000066400000000000000000000050631260276623600161520ustar00rootroot00000000000000 image/svg+xml corebird-1.1/assets/play@2.png000066400000000000000000000040151260276623600163150ustar00rootroot00000000000000PNG  IHDR@@iqsBIT|d pHYsvv}ՂtEXtSoftwarewww.inkscape.org<IDATxݛ{P? "V*Ab5;kզf̫i'I[ǘ&ؘXM}ĘGUAAMl1I;DnVuɈFJ A ]w=9sfWp!Jr8xT@*.Á}($G;|*mW0K@1q1Ebbr %;Y7PJ]El1&@H~ LG_s\p{)Sd> &O0\ s29C 8*Q % `СGkذ6CZ䭢$  - 7ɓ$(Jr%ڄ.(#11$ok/ r`/DI(ɡ=& t/1=0|'> |ڃ˗H8 Ǣ$o%yφ-ƋzI8SXh!aa/EI^"JU XPzqGA_f$c_c3h:|ZFT0ֽ:6'zH"JFnE3O=IHHH8!J<[`*UBCCYgg0U0(Q;,|1I\ADDQQWlK*A+x9e3' (wtdHd$_[7$O$ç3l1Qj//п(/ҳshllij_s$xɩҎx*Ӷ;ǏpKK ;vRZW\.t~/= ّڀ `*84K)luugQT ,T倵N(wPPTBӵkj CSxzHLqPs괧iҪJv$@3uܮ.Tڀ嫀ýGCC#5`MUZ| .,N֜")c EMUj|f,/*a׻l\j]Di#=>Ԍ,.7.k4UlUvb֞3x $;Q%_kAQTW'O8[{;ƌnpuJ))}sݧ_4{uv;0?:zXƸX>dgueܾ<[_2`P .Q%IENDB`corebird-1.1/assets/render-icons.sh000077500000000000000000000003711260276623600174100ustar00rootroot00000000000000#!/bin/bash # Oh god I hate bash. sizes=(16 20 24 32 36 40 48 64 96 128 192 512) for size in ${sizes[@]} do rsvg-convert ./corebird.svg --width="${size}" --height="${size}" \ --format=png -o "./${size}x${size}/corebird.png" done corebird-1.1/assets/verified-large.png000066400000000000000000000013201260276623600200470ustar00rootroot00000000000000PNG  IHDRVΎWsBIT|d pHYs~tEXtSoftwarewww.inkscape.org<MIDAT8KQ9g+7s{3-0)3 DJݮ" '*(vc R+P6jA| gyBݽs>9>GxG}bɴ&RrPJ,0IZ(X2-`ųd:G7FU0'2> lbk[]@Ac{'t41>ŧs˴BE $Rr8 G@{ k^~@$)%16^?ou2!+k^}^w"aZ%J &9wV1c=Z݁(J ^5:>R)Yzc=.`5fl5F[B)YywGW־ E sjJ\T1K`Xc[8Ӽ>%0+)!bvb`C=s7 X+!0u19ݦT:DodG'IENDB`corebird-1.1/assets/verified-large@2.png000066400000000000000000000025311260276623600202360ustar00rootroot00000000000000PNG  IHDR$$sBIT|d pHYs$$\HtEXtSoftwarewww.inkscape.org<IDATX͘OSg?=(-Hːvf(2Ļ9b-nۍwKeYB̺]6di@b =eX]sTZa ys|>uJtG1 Z^[U"p=Qn G9@F,9/uKshjS@A%Db5X ,"˫,U;|"ڟ(;  _MH44JM@ytrl>ID ô=nwG !KA( iLes{F!s{]ղoX/ BiAp$)Ee,6N">mf_/B‘2Ap C82ܭm5-M{;;_^fm5)h cz}&7tP[g]A|?^%ߌBOD?eY}}wd au5T NhEģ\:?p󀿦VÏz*^vX礯+jX^Q,.r醱Ov6Bm-[St kKH@p#A Msq'H] + Ǘ ϖ'SQ8Ț\P籇|/rW8 cZ o",Sru$Ĉ0S61QLp88vgm/={z}]Aj=<+)i8y`zn<\*z/X@IKIIvڽ୮M^Wh{=yEԡ&jl`Tr0V+\2ʧԸ׌63e˜c h=p3|{Tƾ>3=ͥaʇ^r+`%ۛOdgU PRNU&S준U$`Ln<Pb)T#IK*Ifg`6cht`lb^4trEYs2WK[( B \k/lduјJ0i"06s:!&dA]fbve DQelX6DxL Z +e}Ѩhb麗%_ FQTnߌeрj[y4|ظo~X07ˡa=6 e!MP}c,`Ak_1IENDB`corebird-1.1/assets/verified-small.png000066400000000000000000000007601260276623600200740ustar00rootroot00000000000000PNG  IHDR Vu\sBIT|d pHYs a aJ%tEXtSoftwarewww.inkscape.org<mIDAT(ҽJPsonb (? QOIK+4JEQ^.=Y!B@fdE.PB Qr! sJ Bd6c㦙ftMW߆}xAv+$E_F$P%8g\_U b"MI%pfQ\6.!DLcpN .)MWN`21C~y1gh.)1lHNi0T(mZ>._}r,N=!Qڠ\Cv7&®lێDž8^߉ƌ`\}C- ­_dƒ_IENDB`corebird-1.1/assets/verified-small@2.png000066400000000000000000000015751260276623600202630ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYspMBtEXtSoftwarewww.inkscape.org<IDATHNQs3 觩bӪ`Y`Hl5ԍԅ+jxcP76A(X`Lghe@[)T.{~9g)%,;p]he=ƴdbCJ ;W˥JzN%"dגBA x GZULsC1]sK@L<+BhD9r4(lgRJf5fҲ,%~Bd'O˶Z F0+N B'X>b';BH`f(_h=Q~~7r耏hD$A9t x9+l#y:^|fxxĹ#?Wɚ(I‘VW)@ކ=|:={I K].*+|Kp:;nv7rR6 \ 4w6/D}#wL,Ԛ?U~֦V:\hn*'J#L.vW2kEWs=|\޻n33H%4W_0ӷ p\.iA:y e2W ~`Ra00]ĩKRIOFl.d>LDŽ, =ܬpݒ8!IENDB`corebird-1.1/assets/verified.svg000066400000000000000000000056341260276623600170060ustar00rootroot00000000000000 image/svg+xml corebird-1.1/autogen.sh000077500000000000000000000005541260276623600151630ustar00rootroot00000000000000#!/bin/sh srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir # Automake requires that ChangeLog exist. touch ChangeLog touch config.rpath mkdir -p m4 rm -f .version AUTOPOINT='intltoolize --automake --copy' autoreconf -v --install --force || exit 1 cd $ORIGDIR || exit $? if test -z "$NOCONFIGURE"; then $srcdir/configure "$@" fi corebird-1.1/configure.ac000066400000000000000000000061021260276623600154430ustar00rootroot00000000000000AC_INIT([corebird],[1.1],[mail@baedert.org]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign no-dist-gzip dist-bzip2]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) #AM_MAINTAINER_MODE LT_INIT AC_PROG_CC AC_PROG_CC_STDC AM_PROG_VALAC([0.26]) AC_PROG_INSTALL IT_PROG_INTLTOOL([0.40]) # --enable-debug AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Enable debugging]),, enable_debug=no) AM_CONDITIONAL([ENABLE_DEBUG], [ test "$enable_debug" = "yes"]) # --disable-video AC_ARG_ENABLE(video, AS_HELP_STRING([--disable-video], [Disable video support]),, disable_video=no) AM_CONDITIONAL([DISABLE_VIDEO], [ test "$disable_video" = "yes"]) # Vala Packages {{{ pkg_modules="gtk+-3.0 >= 3.16 glib-2.0 >= 2.44 rest-0.7 >= 0.7.93 libsoup-2.4 gee-0.8 json-glib-1.0 sqlite3" if test "$disable_video" = "no"; then pkg_modules="$pkg_modules gstreamer-video-1.0 gdk-x11-3.0" fi PKG_CHECK_MODULES(CB, [$pkg_modules]) CB_VALA_FLAGS=" \ --pkg gtk+-3.0 \ --pkg json-glib-1.0 \ --pkg rest-0.7 \ --pkg gee-0.8 \ --pkg sqlite3 \ --pkg libsoup-2.4 \ --pkg glib-2.0 \ --target-glib=2.38 \ --gresources=\$(top_srcdir)/resources.xml \ --thread \ --enable-checking \ --enable-experimental" # }}} AC_SUBST(CB_CFLAGS) AC_SUBST(CB_LIBS) AC_SUBST(CB_VALA_FLAGS) AC_PATH_PROG(GLIB_COMPILE_RESOURCES, glib-compile-resources) if test "${CC}" = "clang"; then CB_CFLAGS="$CB_CFLAGS -Wno-incompatible-pointer-types -Wno-incompatible-pointer-types-discards-qualifiers" fi if test "$disable_video" = "no"; then CB_VALA_FLAGS="$CB_VALA_FLAGS \ -D VIDEO \ --pkg gstreamer-video-1.0 \ --pkg gdk-x11-3.0" fi if test "$enable_debug" = "yes"; then CB_VALA_FLAGS="$CB_VALA_FLAGS -D DEBUG -g" fi GLIB_GSETTINGS # Gettext stuff GETTEXT_PACKAGE=corebird AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Gettext Package]) AC_SUBST(GETTEXT_PACKAGE) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.18.3]) AM_GLIB_GNU_GETTEXT AC_CONFIG_FILES([Makefile src/Makefile ui/Makefile data/Makefile data/org.baedert.corebird.desktop.in assets/Makefile assets/256x256/Makefile assets/128x128/Makefile assets/96x96/Makefile assets/64x64/Makefile assets/48x48/Makefile assets/32x32/Makefile assets/24x24/Makefile assets/16x16/Makefile po/Makefile.in sql/Makefile sql/accounts/Makefile sql/init/Makefile tests/Makefile src/util/Config.vala]) AC_OUTPUT VALAC_VERSION=$($VALAC --version) echo " Corebird $VERSION Prefix: ${prefix} Vala Compiler: ${VALAC} valac version: ${VALAC_VERSION} C Compiler: ${CC} ${CFLAGS} Debugging: $enable_debug Video disabled: $disable_video " corebird-1.1/data/000077500000000000000000000000001260276623600140675ustar00rootroot00000000000000corebird-1.1/data/.gitignore000066400000000000000000000002771260276623600160650ustar00rootroot00000000000000org.baedert.corebird.gschema.xml org.baedert.corebird.desktop.in org.baedert.corebird.desktop org.baedert.corebird.gschema.valid org.baedert.corebird.appdata.xml org.baedert.corebird.service corebird-1.1/data/Makefile.am000066400000000000000000000017571260276623600161350ustar00rootroot00000000000000 desktopdir = $(datarootdir)/applications desktop_in_files = org.baedert.corebird.desktop.in desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ appdatadir = $(datarootdir)/appdata appdata_in_files = org.baedert.corebird.appdata.xml.in appdata_DATA = $(appdata_in_files:.xml.in=.xml) @INTLTOOL_XML_RULE@ man_MANS = corebird.1 gsettings_SCHEMAS = org.baedert.corebird.gschema.xml @INTLTOOL_XML_NOMERGE_RULE@ @GSETTINGS_RULES@ dbusservicedir = $(datadir)/dbus-1/services dbusservice_DATA = org.baedert.corebird.service org.baedert.corebird.service: Makefile $(AM_V_GEN) (echo '[D-BUS Service]'; \ echo 'Name=org.baedert.corebird'; \ echo 'Exec=${bindir}/corebird --gapplication-service') > $@.tmp && \ mv $@.tmp $@ EXTRA_DIST = \ org.baedert.corebird.desktop.in \ $(desktop_in_files) \ $(appdata_in_files) \ org.baedert.corebird.gschema.xml.in \ $(man_MANS) DISTCLEANFILES = \ $(desktop_DATA) \ $(appdata_DATA) corebird-1.1/data/corebird.1000066400000000000000000000023001260276623600157350ustar00rootroot00000000000000.TH "corebird" "1" "08. Feb. 2014" "man page by Malcolm J Lewis" "" .SH NAME .B corebird - Native Gtk+ Twitter client for the Linux desktop. .SH SYNOPSIS .B corebird [--tweet=@screen_name] .SH DESCRIPTION - Corebird is a native GTK+ twitter client that provides vital features such as Direct Messages (DMs), tweet notifications, conversation views. - Additional features include the ability to change to the GTK+ dark theme, searching and media uploads. .SH KEYBOARD SHORTCUTS [command] .B [Ctrl + t] - Compose tweet .B [Back] - Go one page back (this can be triggered via the back button on the keyboard, the back thumb button on the mouse or [Alt + Left]) .B [Forward] - Go one page forward(this can be triggered via the forward button on the keyboard, the forward thumb button on the mouse or [Alt + Right]) .B [Alt + num] - Go to page [num] (between 1 and 5 at the moment) .B [Ctrl + Shift + s] - Show/Hide sidebar .B When a tweet is focused (via keynav) .B [r] - Reply .B [tt] - Retweet .B [f] - Favorite .B [dd] - Delete .B [Return] - Show tweet details .SH AUTHOR Written by Timm Bäder. .SH HOMEPAGE http://corebird.baedert.org/ .SH REPORTING BUGS https://github.com/baedert/corebird/issues corebird-1.1/data/org.baedert.corebird.appdata.xml.in000066400000000000000000000032341260276623600226150ustar00rootroot00000000000000 org.baedert.corebird.desktop Corebird

Twitter Client CC0-1.0 <_p> Corebird is a native GTK+ twitter client that provides vital features such as Direct Messages (DMs), tweet notifications, conversation views. <_p> Additional features include local viewing of videos, multiple inline images, Lists, Filters, multiple accounts, etc. http://corebird.baedert.org/ http://corebird.baedert.org/corebird1.png <_caption>Generic timeline view when using Corebird http://corebird.baedert.org/corebird2.png <_caption>Typical Twitter profile. http://corebird.baedert.org/corebird3.png <_caption>Account settings like Name, Website, Description and Avatar can be configured. ryanlerch@fedoraproject.org GPL-3.0+ Timm Bäder https://github.com/baedert/corebird/issues https://flattr.com/profile/baedert corebird-1.1/data/org.baedert.corebird.desktop.in.in000066400000000000000000000003441260276623600224610ustar00rootroot00000000000000[Desktop Entry] Name=Corebird _GenericName=Twitter Client Keywords=twitter; Exec=corebird Type=Application Icon=corebird Categories=Network;GTK; DBusActivatable=true _Comment=Use Twitter from within a normal desktop application corebird-1.1/data/org.baedert.corebird.gschema.xml.in000066400000000000000000000076251260276623600226220ustar00rootroot00000000000000 false Specifies if Corebird should request to use the dark variant of the gtk theme "Never" If/when the user should be notified about new tweets true Whether the user should be notified when another user mentions them in a tweet true Whether the user should be notified when another user writes them a direct message [""] List of accounts which will be opened when Corebird is started. false 2.0 Maximum size of inline media to download, in Megabytes. true Whether to show the sidebar or not "<Control>T" The accelerator to press in order to bring the ComposeTweetWindow up. Must be parseable with gtk_accelerator_parse "<Control><Shift>S" Accelerator to press in order to show/hide the sidebar "<Control><Shift>P" Accelerator to show the settings window "<Control>P" Accelerator to show the account dialog "<Control>K" Accelerator to show the account list (popover) {} (0,0,500,300) Size and position of the settings dialog "0rvHLdbzRULZd5dz6X1TUA" The application's oauth consumer key. "oGrvd6654nWLhzLcJywSW3pltUfkhP4BnraPPVNhHtY" The application's oauth consumer secret true false Whether or not to use double-click activation in tweet timelines 1 Bitfield for text transformations corebird-1.1/data/scalable/000077500000000000000000000000001260276623600156355ustar00rootroot00000000000000corebird-1.1/data/scalable/actions/000077500000000000000000000000001260276623600172755ustar00rootroot00000000000000corebird-1.1/data/scalable/actions/corebird-compose-symbolic.svg000066400000000000000000000054371260276623600251020ustar00rootroot00000000000000 image/svg+xml corebird-1.1/data/scalable/actions/corebird-conversation-symbolic.svg000066400000000000000000000050611260276623600261400ustar00rootroot00000000000000 image/svg+xml corebird-1.1/data/scalable/actions/corebird-dms-symbolic.svg000066400000000000000000000113241260276623600242100ustar00rootroot00000000000000 image/svg+xml Gnome Symbolic Icon Theme Gnome Symbolic Icon Theme corebird-1.1/data/scalable/actions/corebird-filter-symbolic.svg000066400000000000000000000047671260276623600247270ustar00rootroot00000000000000 image/svg+xml corebird-1.1/data/scalable/actions/corebird-mentions-symbolic.svg000066400000000000000000000117131260276623600252630ustar00rootroot00000000000000 image/svg+xml corebird-1.1/data/scalable/actions/corebird-new-window-symbolic.svg000066400000000000000000000064511260276623600255300ustar00rootroot00000000000000 image/svg+xml corebird-1.1/data/scalable/actions/corebird-retweet-symbolic.svg000066400000000000000000000102331260276623600251020ustar00rootroot00000000000000 image/svg+xml corebird-1.1/examples/000077500000000000000000000000001260276623600147745ustar00rootroot00000000000000corebird-1.1/examples/.gitignore000066400000000000000000000000541260276623600167630ustar00rootroot00000000000000tle mm_widget ab_widget crop_dialog lle aib corebird-1.1/examples/Makefile.am000066400000000000000000000030311260276623600170250ustar00rootroot00000000000000 AM_CPPFLAGS = $(CB_CFLAGS) -I$(top_srcdir)/src noinst_PROGRAMS = tle mm_widget ab_widget crop_dialog lle aib tle_SOURCES = tle.vala resources.c tle_LDADD = $(top_builddir)/src/libcorebird.la tle_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ mm_widget_SOURCES = mm_widget.vala resources.c mm_widget_LDADD = $(top_builddir)/src/libcorebird.la mm_widget_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ ab_widget_SOURCES = ab_widget.vala resources.c ab_widget_LDADD = $(top_builddir)/src/libcorebird.la ab_widget_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ crop_dialog_SOURCES = crop_dialog.vala resources.c crop_dialog_LDADD = $(top_builddir)/src/libcorebird.la crop_dialog_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ lle_SOURCES = lle.vala resources.c lle_LDADD = $(top_builddir)/src/libcorebird.la lle_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ aib_SOURCES = aib.vala resources.c aib_LDADD = $(top_builddir)/src/libcorebird.la aib_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ GRESDEPS = $(top_srcdir)/$1 $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir=$(top_srcdir) $(top_srcdir)/$1) resource_deps = $(call GRESDEPS,resources.xml) resources.c: $(resource_deps) $(GLIB_COMPILE_RESOURCES) $(top_srcdir)/resources.xml --target=resources.c --generate-source --sourcedir=$(top_srcdir) EXTRA_DIST = tle.vala \ mm_widget.vala \ ab_widget.vala \ crop_dialog.vala \ lle.vala \ aib.vala corebird-1.1/examples/ab_widget.vala000066400000000000000000000003131260276623600175630ustar00rootroot00000000000000 void main (string[] args) { Gtk.init (ref args); var window = new Gtk.Window (); //var ab_widget = new AvatarBannerWidget (); //window.add (ab_widget); window.show_all (); Gtk.main (); } corebird-1.1/examples/aib.vala000066400000000000000000000014711260276623600163770ustar00rootroot00000000000000 void main (string[] args) { Gtk.init (ref args); Utils.load_custom_css (); var window = new Gtk.Window (); var aib = new AddImageButton (); aib.add_clicked.connect (() => { Gdk.Pixbuf? pixbuf = null; try { pixbuf = new Gdk.Pixbuf.from_file ("examples/media1.jpg"); } catch (GLib.Error e) { error (e.message); } int width = 500; var thumb = Utils.slice_pixbuf (pixbuf, width, MultiMediaWidget.HEIGHT); aib.image = thumb; aib.start_progress (); GLib.Timeout.add (1500, () => { aib.set_error ("Image could not be uploaded: foobar bla bla bla bla bla bla bla bla bla"); return false; }); }); aib.remove_clicked.connect (() => { aib.image = null; }); window.add (aib); window.resize (500, 50); window.show_all (); Gtk.main (); } corebird-1.1/examples/crop_dialog.vala000066400000000000000000000001721260276623600201230ustar00rootroot00000000000000void main (string[] args) { Gtk.init (ref args); var d = new ImageCropDialog (1.5); d.show (); Gtk.main (); } corebird-1.1/examples/lle.vala000066400000000000000000000007451260276623600164230ustar00rootroot00000000000000 void main (string[] args) { Gtk.init (ref args); var window = new Gtk.Window (); var list_box = new Gtk.ListBox (); list_box.selection_mode = Gtk.SelectionMode.NONE; var lle = new ListListEntry (); lle.name = "Test List"; lle.description = "Some test description that is very long, much too long for the row width"; lle.creator_screen_name = "baedert"; lle.mode = "public"; list_box.add (lle); window.add (list_box); window.show_all (); Gtk.main (); } corebird-1.1/examples/media1.jpg000066400000000000000000043344631260276623600166570ustar00rootroot00000000000000JFIFHH XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmC     C     E!1AQ"aq2#BRb3$rC%4DSc)!1A"2QaqBR# ?S>Fb> FmbjLlR$OT`v n5AHn Mn4aMREKofs@abD_039V7 9mFT٢D(2hݱM[K̙3A"VEـIrI"&+Fk"P 7WA?މYw95ZBđU:-s<>1,Z{A]_V [268H-odo?j3.!$vк DP߹j*ڴh5k0TiVldk4{F?BєbLgI6I771Ҕni4vjGAMLՔl{dcdqWQb,m&L:k2ITnD65tQ; *BzgP*jENܚ@34(R2 # Wh_WFș޶T ˝J- X/5.2s\n1540~3mKzjU:58̯?hCڀ[ZE[Wx}U\gSF.Ò #-h;Ҫ9n*{MVq.[trx5փ5: pErWu?Pb ܬoW׫}7Crp'/ aq\o+{Ϲ64XދjYFqE-y5M?VE` `H>\5Wl (k[ "$Wz\ӆTZ{D@khG"5B[14TT#5@S2kE{Vvx@gmmMZpP:oiZXo|rc?4z~*[7o`(f:$-/p?j0h1> N5LXz[pނF\dsVr@O~ɸ$HL(XR(cn/:EmYHP9;; v?4`V[$Mh` D#pLwt=R !h&fE#e["PI1zo6@jDѨcEq={ Rv!j023ֈ1mÎh{-m(2kcpTT-+am+GZ .C3Uy«Ev)t~*/c=+@oxPx1'PUbղ>ePP'c D4OX od-sY+&>d1kmP/ikmk|u<$kTzsX4"&c[Ӑ3@u)pFxf_P-,{E$L汲3Z3PCzwy ,2i [ gcG;tCਃ5s&\ ъKF:HV9wv<_!lZ|S7/h7׊4 MBzL!kot D63\mEQ[^C{'S,vަ>bƾ\2٭^ViJ{g;UʓOS`Uh̿=4FȚ Mgp$֊74r$V``gPtDO ~((<9Kћv{DE{d֊&I?ndb1TsJXps@# sH$ *oq#*.~@m7T I ø`QzVpq(In&xFbffk$$n#&ڵj=6|`zq :"eH1r?k-^7Ұ3ǯu}?Cc~*O%\:^>kT?WGxom\|TwzRt_PS[KOܚ`MP?`GjЙekblTKA2OH 3@RpY`  EmH{s3M`݅4&91V[[DQXP"&c=MĖ w$V@l ZcA * < 0=C򅡁@" 4 h#3e [4b%p{wfwkd@P"w8TFӞ( ďjJ7 [%A &A`fA蔮D QQN84i0;#!ƚDV(RF XGPAPah8AW%y4M9$cF&˶ ,6&d~hJ?z0;XeWй`uNs O4]46$~~Euf~mG+u Ͻ(OXPԔ̘`@GCRD5"Ib,MDkbq SkkdMm4V$EKh3@ZqA;9R3eف#%3hNh"'j,հFKT@h 2|GiEMVrP="(&Ml!ok;V\q@JG#޴EmI %2}Y|ᶯZVCE [D"'5B"ɠ &e :E&`P%H# & f$ HQ)!z̘7@.cz(GZ7.bzcަbI~e40 cӉ h'"=&͚&)JPI,2hj[%ZO⌢1ȣQLP8hh`xn?h^&b nX5F0*ĿP(%nܚ D{Q="Mh7AJ }#`s3m*F<1E""y}09()j4 x{D bqJjH`,.f?)+2bx)@*yZ GdB䈉jV| GMV@p{^?LPŋ~$ 8~+OHB(AchH=rAȢV"Ϳ.Q{dVXozH+w54H5LCo5fjZvm,.nb3?W`.#-_RΝv(]@Dď[#Y#RnmJzƳ:O%MkW[BD+\.V}{Bm,tx^♲.^f$AD)stzӿ_D/+Rd95u/oރsG {jup uX -U S@cJ"֤qHr܁#@Em)3ڀOgh@%E`Xk dM}9' 9ىQLEOɠjL Fbw-PW'"N  /Aw,G~fAhFTZj0+#Px=JщC#PJ"挰Ɲq[1A :@4qFR@ތԷF$0q@ͻt)YYs8 ɢ 9#IM3S^; 2(' $qڋIA另5?N&+# C{C E5{sޖMX"2kcH?zRbxFn UڤO޶ bn  . !H4MEc~`vJ3NI$yr+=YʌǯMQPD)o[Z,ŏ g@JPD{P-FQ"x9IyBd55RI?j)34ř(8=:%Ff(&MAhX` )@H(Y(rTr ,ȩ7hKp5lIDē@b("q=t&;60h3*ъƞiBqABiDAiq􈠃Q .c)E{Ѧ{*:A,:#Î<`Fq{N1ns_,T80uk. r*DWuc}Y3 {E[AjOIgw OF[ ǽJP6_~Gz+[5lCOE;Hmi5rƅWHiĘSMjTuz`[ gĀ@d-aARAtHCJEV?Тqlf"@AT`bӵ4VCij;xZ,VsL3Zb$ku!6 Pgh*]{Q8r(8?b2@06m TbMhձ-U ֧$ հe|pOj -JIzX\k`+A5x%lSf[Fj/.)V3\zt|'@L{t?\;N[OyEˇd&'koLO U|i9,Džyi#] ál1xo qNitz/0gCP^WQLq@6nkDNhmmuJ lj,HUcM$+e h@Z;sj$%޳Atۏ4}>ލ rh <PVܳ*n?jt F=[݂""K`~K/4 r^M 5#q!j Y(#B(윞hen6mmVDхTs4ԍśpL,p95 bD֡5Oލ#W9sU͸c@&}C\cJH5iIaf105)H'nH++L?x*Y]bpI5H@3W_vy@$h+o=û*_4ť0891=с0sFٌє51[L84D3XB4`%*(OZ`J\$|PMn3@ցB@E8_$PJLP#l@[h "EvEm83A+Bir$NM $j `Tid~h2 UΜjFaLkPʎ&kD X~jD{$Q坹D@e.Hzƪj/4 "Si$.'"L;ՉpHڦr{W DTPej@N$N}=b_}m԰3jN8}`~(PDUEh)@Ȏ*p>4"c55 q[Dk uB=h؃]%@CÚiVf$Ir ,d֋)gaZ -Ƞ@H`xAM,k=1h>M!@BC \*@FA,55Bh4Wߊ ށ…:@A6F#ޤP(rN_Pj2ib V茕5B5xX,^,悭G4RXF$f_fh+r Y 0hbL*ddzb֘'WC.ES}!HLؖƗ<${'[6+axUcιl#tcw5$ޫߊ[VmN ۚo/W61{aD5jϵku^m88wj}:-+kAeKO#ޡn@@Cy k{I LbgS$bq,s5In`29x}HCŕiWԡiS\ߊROMS]zhun15cF@(3cO@6;5̠ jj 'JzS*5RI;hrLOVXG9O+~91uZ $ stůt Nr鮣Z_Q-yV-S~57K7ݑ'8|7DFcߩ>75ᦰjKx 5pD`iNu ;VM4A G>'@h96]N1@&ҳLP Y(1[%nF=F嘦yw,giKBH.umg5ohdcq@7Z!fEh,fy:l7PnB,e6?Ѷpz{QGު0 z ygnh3@b*BPհ3+@hպj*K4׋[j3Z~JOPqVgRB[+Ͻ5I1H`FCx&RӒȠ\򁃓AׅrQ>.W\^9o@yF]B'o XS/U3{Jc\t6$ V ڷD ߹4 =*{D^Mn@bn vd %+:)[}@`8Sgܺ9M̙_}JD挧"іhILe&8Be*X`Eg3+4H^Ib.680:H2ְ`I u(APJAYlt94Љ"bEM@:R{{ 5K:}9.TkDYAIj/kd5ZWuwbZ$ij @i+/љ\3zCQ:QXz0;j%$qU 0Jt?ַW-®E"GVp9OFC^ƃa1TҵmGVo]4f.J^M {Ĝ_VYjnz٪qV(98Z"`(Jv wwԆ榪 AQh,,}M[{B!PV#F5LIFƖb ϵ1}9-4X3h4v5ii/U:s^Z x6 V_eRI3=4q%bYC; P(RF++qSSmLk".bhN*[b1?41n`? ]K>bq  2~PH[ɽکPV{ 4dځv1V+]&;PE,Q6Ү:3Z< D>OL `P{L-(@5Z(_ҕjU=$꓊-.+VZ&j$~+uvr s[ B9hbP9tlGX5IAZyA?qz(9u`b ļ`j/**hu7ZQDJxo .+ٽX%C\`Cq\z]Mbf>{W/UGxk'bxz}b/OjV?R T"$?DžȖcQzˆ`!Pǟnš1Z",8A,n(LjrU< .EKI@dj\l"[ȒOJ=z*6$_Q҆k AjBM @ޅ J = \EHs[b[5Bb6nIW8wt>hw=mh.Z)3l&&ՄDhX}nqA HLb[G$D%4 ַ,P@[tU= b@("_qAǙ$Q%tȑ&h_ 3{PI&`&fSϽ5*KsXa*+ IMcB Xg\"lZ۲Tg>,DVc.@[M{>A ހLbEc4 9u5ǑE"-m1@fP* jX(BQp夎b$3A oXgMPLmȚ8M8?58JO @jH9 4 AlPMDN (,8=h/ނMoq@@2z qhbj`gIaˌФ1?2Nޔ)#U  g7 C,jy@m8VT31 M {?L|ш@@P%D3j,%x Zh'H{PDߊ57Hik0bxnr3!fI+7H`Ե[~ny4ew~67sv>6{U&U6[[JWf@C&)7V]Uo4MNjE$mf 8C`2<&Ew7OH={N5ܘ'1_lOL@ol00>?5! ZhyE`  Lњrhf9&nXNkdHiw5 #HIvF%lsZzGJk{DA$]@6OgP>hh"{ 1? MPuq:ԈS18bҞM0>('% Q)+CpwcgAZ ) A/`dP0p kRhYhkR YCau(+j<7pёb n̢ߤSV94ћmR3k7&EH f Pm=85 /\ .ǵf1whX6$ɬm@qh&-n5ay`<~(hn&EOPA?niy5+\hb z ϧ@4d@j h*6<CniJz%RF.Y,**=F' ֔;pBoj™tݘ/l[]p[ Z؃]tϵhPT ڨUDF,2ON aP,9@hA dјEg($K2A#3vV 9hE֊Ld> UDUdzȑM1"XS#"l[S؀Gz5--ezqHSߵhHP9LDewPHaf2=*PVɎƉM?z;1lypɸI֫F2(M̎,5#(FX]bHш8^_Pn@8։bO'B dI^wdwOo1(+^Ķ3P'rIyl傱zHޥ״15x~BeTջ|+XJ0x5XJ ձU$$Q#15f,A(,yu>Oz "=4IdiwbbiPebK#MXێ@`̚se6hE;!e@&UVг\ȩ:9-őh-n'A0KdTr\"q[}Fn94f_֐H,kTv2~v۳nI`읱{ޖ9p U@O唀@ق}n$UteYMC튱k ٻ'3NqԊԦ<5&>d & ,c`c2EBNޝԍh/ٶcY[GwL[_MwQD>٬k {Z ocޯ6ޣsS5Z> ;\wʢ4omqx\fߍ_]<7YӲo5~sLx\o*ץ1F}‹f6¾/]UIPyVp*Gan?z '%}j3E)W^~թ[HT64kZH{P ڂJI"9I3{;S1T#5Wcχa`f o. PbP|;J,WݧU5$浆l怍aE$.>{qX4#M%"E5sażbhD //ff+pZA  2A2 =G_|h9 =EevY@۶'>!sA((W_O_"(󙠝yډP&+vEnqw+C0 db2&*ø*Gj*5@2LF 'G_D%r(%hr@ eMh"(4&ј;40@бF#1$Ѓ>lA`m)hj(б0jV] MH'г,iG5k[o,vKVzEn9{tXx&jmAf0fVe79:ٖȪBh&+`'U"D+j U2d`P5Vf:買f BjZkԌC<+LwcϰLj}..gktsZ%!F]$ U3؟UPb4P4,}Wj`~ `}4rF(~ L(/ix$w#7WM36naA";EAH4[o?`X^~Rekfjl2HόMuE0y;:6c̕&GS \xqbn4A>4QzV5^;xd"kq#|"9zk ބ0ڳ|-9!F>kT_n@\e[/NjpjlTe[AIZ~dbv>j6Ͻ@t~Plh/i!:UJSO⭌V8޼bKX=5 $q[w'em*5 b4.i1@ E `"b倿z By1[)bcT!3ތV}("@[DHT+n$Ď^?5gmFތB坢B⍐hb}63?5$fݹS84@nl 6B )Z -qF$m?M1 3&,Ah&K1?5MYed Ѹ ShbDִvhn!P@1Z1MvH=>P0ff{PGp‘@8DHЛӎ84"%Hkm &9 Q'J@Qޱfk6Z& AS?Ҫ L\YZ3'#^?h[E#S߆iQWRsQUk։a1>5n”Ț: YqXm4KJXn[qUĚ0I6?0MZu.ث`N5?N%qUbFK:̩j 'aEb {Ԋ|c*?O>Չgj)OPP쭘z f8X<5[d[ 浘 y Q>dVm#mh)j4ګE+C#3Me<,oi X҇bc5IS yglfZyr,;"IVkwUӤOR(x-Aq3Z9mӾd'TD`x nC[ #"")_qi?TuΑFԋQݵUt7EpǎARno'oykǨ}7GKwH8ʧxGֶx;/ .ROZx$ >hđj ;E88U$V}<(sLkeh,S5NDԫ&I=E{]"tn+N?40;|qTUkpD6q&/ Gzt6 {[YZ+@F4H-fh RWl 1چ ɃVp(aqb>^@$;IĶ 3haBcE剀nd1hDZ%ɚ$S4A&$X#3)ݚ I4f ˻=;Ui`P vq 4%>.+[9kޓZ-@PîsXOcY XDɣ`W`.M0EBwMYGzԅh V@3>扉 s[* Z` 4*T3A'AbF'I4eL@r="@314`eU?f- h(/sA(A%0L(1*O^ 9#5 "Z ށAU(ؑXfLYP@ 6n@4Jew1A$n.i"{Zò},jty>ƱU,ѨVlVPb?z6R+hķ@?L'$9O8߰ҨA;I `~K13@٠y1CrOby;\  2P6'+Kl.4"=^sAUV & ZMK:7;MR'P$T\3"RdVL.X &V;Pֆ+Z{d1s^%k߃Dx-h/%LXk' i՛R2)ս>p+AŠLEh0D`y4f^ 45SSz3UokžA3YJT1-wvb18 { X:ZG5Eg~q=7nP4_[["mhrA<;dž:-n4zOܠC4јo@ln/Y5b3Ui&:f-Y-RVg]%M:9D"c(!s .x:ӖPDL~2+xH튩AxnN!-=jڙ*+Bj<-i@tsƪ>g"xǺts`sZs&VY'"1 T7Sީ{ bjLcAH&mٸ K5*nVlUx]R$b*j&IPJ5B@SZ;xr@H54nip YETf4djM+ZO9x")σiLH3r]-_NZX$5&BL>jf+,E3ֹV6ӎ{ kWL@RUڟ'l}g[(x1UxVLՌO׬yf[DtB3[(Zkp{P ISEK"()>L5*RYNI?˒zMVILSf'[!J}VXU nLՄԆX):/z+d x,qkq}=qḷ/%3csZ>T_ʡzۅPTx֧}Cм X~yt;$ eK&~Ds\.?_}C*Br=zbzg$OqQbτ}Zw;'A#wK+q&F{8ыuZC2PY`'@7AV}.8*UHvAZ搶jIڊSm1 n\ӖMJ,q4OzjR86zQQ"(l: ,`E28֊״in+t hր(ʓn5`M "S84B6 Zh{zU'BI4Jh G&{aktEX%A`#{m3Xn. [r(!zA0#XJn;Hc[@qM11nGcr(p*}5 k"7~h5L FE(TqT^hKnѻo^ ] f3X&o5bD/=Jњ[|A23#2v4 JWSDPȀkX`ѤdsA;vzV !0@h`^0"4E=iֆ("͸{`14jJA c3~h- vnY"߫=)W9VDf\\bgV&O-dށ3Z"Ț @dPKn@v`1ێNhTwF&`vڅ'Wh wp+@89WdFN>*Pv#pD?t3LPE@t!ȩ֓*9F fOQOtȑD]"߫mEEGmV5v̟ALXWVZ0A2 !G>6ST趁1O`EbI ENٱ`h0r2}Cu<Ѻ6YPD<ѧg}#hn;2$h3MH\DӋǵn$bLH/<CZ$ш&=_}EH1@eӑATpb 0 -KX4ld:ZUs2Ϫ`Fp*hـhtޱzptчe#5;VS޴Gw0($cx@ɠq”3߽sAZ:P˂{Ԉ (:G I56M`A@Ŏ("p0sA]Ldb#yDE ؂Mљ%d6QY"7XhLƱuQ Ht3Ҙ44z녀-zZKc  ֕I9Kv j(J+q*D! N4bI -w!?&Ef +Q?V[>^jQ?kxĬ҆Un5;$ɬkKUEcTᎣCc5: ӳ=Z$&o{Ս{z֮S,+EnYpfjVtELUk aTMF.)[ĦkH(zШ$YhQ򟭭o 0#獏J􎑏LkiݤvʰG5CKO#ڪj~*Hwzhː6Չ>kt 'Pji-N쐢yv1xzn&ikg FZ<;… ]+ϵvi! 3U\m*"* eTAFs\Ti.kXW2#h|TFc7]['K [0Oڃ YzUhGB{VYeDNhʓ@ (H6?40 sUB}$ ^Z{h{E3D@ Fi $U2 Fc[kcoj0MTA>I2=M^[ұ[ H*4TQdɣ1>nBH~sߧ $f[U*Nr;3CsOzU{zy\Е`G\ 9E:QJy>î+S{|7$Ď>k/?zoNZ=q WcQюI(CV }'Mּ@D*ZXN PnX(T:bI$VitE=FheT}4}gVm9W`g+޶6SEV=) *)dHE.[k@Zc'7=}"mSE zނ1D.Z$ځ@8@7H?.gwNB&s=@P4lT fA ֿ4 ֆDG  ~(A2V(1 sFZY5%Ci9wa+0k`@c#d7<ѕ/.Sj(FkR(VmzQclHh"Z6 @3p}QFT㷽A`En݆`V7msc(7$ShU%B…EmPIU1j hmj01 ($wv#(۷ P$TBOz A@b25$Ҁ (d i?5- 0E7AnpCzhùɫP+cAk#@O,DP T(' f(Ed#E ;",ͺ9lIBϦ8=Sb "IMm]Rp"#P3 ($ yBF@T]dA~֊W=ͽI#kEmᔩh&zP"v`P& 9R`#3ւ-<`5A), k#4 T_zīXGz%$@Pl\ \&0;S=Q1o G1c0SmR S?nhauAi#Hi݈Uu I8/]٭kewڪQ֋*WU{It=PތȬ/ז|X$ړs<3+0y}+M} z0o}=RiS-AդoҲ#VhA[ $ZR:`Z0dT4M:x#FNƇkü't H?fOĀ˞·|Hf vYJFkm.UFD@* Tް1`+W`s,}~dEqQ[Drt$p4ѥcR#Ԭ *\Hإ*Hz1cMV8ɉ9ql"v@l7J@FM+ X,{O ֤k&r+PXb{V79hsKhC"Ywt* [GS-ҩλbN5b Uo k0 *`fSbW[+0{6I& VRTiHKz1 dkGxu TX ]Z)xW-Aq+1ƻ4D^,rtڝV!Ok\GY]G}u"O~z/lpojIa`+zj .23W?2y*cS%66:='B44cAJ5DznIhXV\҃(*]"wtjҩwO₣ؓ$PUd1(*fHM"8(aI x8{aӂ \{DEGj|Pkp$Gd'C˓ڂ&

Z& VBJW2KϡLJݶV vR'{ &z*(;X Uo1SwctV2}Z HhIq{Ѱ{ g憴zrji{V1p9FsҠ V&}>R&XH^h3f탙=C9Iz&$aD{Q*1o(P2] >(pLբj1R?沄I=J;pXkιb 's 58ӥdE09Af( .n8L3X X 3BSE3ւ z$sV"b#DolPH Ug<`+X #814 &(%0(# b}.dե?zn&OI 10v&` :1A7+`q@n)?j%D1LxXf ->1` ~Vdffx86zcma䱉=գ V#ڷ&$ju9{d9X$a`ҪmIl fo1PΘyJ# l* l.4k7>h/i5% `:H<5iA !o*fsXfݠg$nȦkmf}D#ކ5; ken: cpLWIYGs̶ X5VTWWlN hI:ߡPJAbk#cU6Bw)oh&d?`,g&*D;uP}9s*m㙥>Ԑ+_J^`k;jÙ me-lɦ7]qG1~-FqYXJaqy\GuM"^hU z7dيMہ=^{>`^w[/Z=fc->4ET2hcjETfs["FhO镑un+EP:gP yI@ #4e3ZQ!5hk1V&h/im9'"_c)m'lUm1@.i$ԩj4D~n9V+qUT.p@JeU B$QzUY>լ(y0=T&;mln<-w ҧ4'?jcuko/#gu\S&x\Ub- ø5Ǯ4Ujt^yz˦I[w/2@3W1_L LdS|zw|Tb>6M }AuDF4ljQI@e*փLX޷E[CU*qT@0E5BqM/hqB>b?4VmY)$niHP 9nRiMlb팈[ڦE g,A}َ(",h"ڀwS2h3=2D{ 3UZw.?M9Y358p-0+-(q ALbH4k[[=z~h, kk -;[JLERh҃L@FT3mFeX\(`&h;""ə$P>ؚ 3C߽IA06leT'T1*n$YL< ֨"L4b23޷Y`&P~ktF$bA{PD ^ځmYI:e%Gz0j% NypCP=3@'1U< c*E"dGg$4/YTӴ e%~A0PMQCsAEV9TJJF#?z@A_@)*7EuS MM\c T=i({[U OZJŸ4a[SN(kڭ00( w8ɭ pZ- @SuD5ͪINje ;1UdG CLUWM+^  lk$#4nٳTn":T|' bUP3S`ށ@Pr+0:zZ>^=Qr:VkY3D;PInc-%|@Aj+Nm8憈oZg0PƃIjgSA'=f:%&IxY Z S5[zkT1RZȚ-˓9s?4YkC\[ msMPPC{PT2Mp(ia#;y#(XH72?f c4i5!DupیP:444G@Fi:Ҍ0]XP> IF("14 KOa-bkhU;_ WȚ+UӥC }x 9xѻXR~[Eϣ [-&mg)rV u*(?X1L~p@@[_!2R k0+B<'V-`sZoٗo#$G֘ƕ.[*LV4_J[Dn5p=![AE0=hUV{`b حs]i \oj_}AkNTW;ڱqJ=Xx۸ir5:kKMvW3Xu4lDލY@R$.C8 )S'lnV6d5ah586ኡP&:j%oIp*Pj(EZ!$jmkRcfVv܀2Ah"Oj(+E+tWܼSLTCDLtSQ&Gl SN$jTmj1CSDV\RT+tIJVت4KbzC3ރ?]ዩHiG= Ylm$ƻ\!A;nij/sԺ n `'^7~zvNn[I~^5J_`/jF sSz}xŢFLzƻ :)!OD71pE>,.55mk \P 4O0L 8/[ ), E4W})i`z_MPr`AY2(+om4" G@L$3X$Ooz'A5+ P nu @6f\FLhB$06 =B6(ap$rh!@3(#zuq5:^yywh` _/+C%4'InT[S4q@l%F:>DA@2E@H'zO46V%T @3lT5 aA2'Wո VAkM:[*1n'֚"UqY)<', ւ.i$ɑWn+;n"7W4jQhֱc:]Hбi`c榭5 ojrww4O;pT3Z0<ԭ D*q ۚ'rDI$\Wr1E!A4-@D怎[7?"$5^;;"4(`AZGϼ+y5bߊXjݿ&R&\3h8+PS&,g55Q3SfL@YCz7/{9&wm=מ QpT(`"p_H?+C8Rw=P}?DKӏj0z}hosX: ~Ӿ~:},|A./94VaU+y8/i}1RE{HC`b EsIV$q[X;*oiO&Hz5qT y]TE X 0@+wGJ\ `[dH5 pOZ{36TZg{;VZz;XK.8+dsP441F5]8@`r6[vf:Ɏ %k0I0R!OJ(VAfv:P@YW$MR1ҵ$sڑg-8VQ08f6Csxy-cՁYUM&,B3AKO<'^^I wk_MI1Sy5kj,Tj+1:[qVSŁ9jĖ+1AfkjNh kTw yulzZՐ?bp9Kt!`WP 7 ]("A0dABq@ѹNbjJqoh"i?`GIz`mքmԇ`sFDTJxD˙l*`ۊ !dJ6e%f5t^;7W*km"Jm[`ֽ]t]&Um a[Q5RL c?S+ h{B8c9`b(h-\޷VB 5Dyͷi*`Zʋ "@@Ex*LbĦWi@$`{BH3Sb7P" VhH̜|ѡcf`',Tm9h Mr:ФD,z+D8TXf1ҁnp6 p0M5 @}A%]A3U(HLXvB=B}^3PPZl.vLmڤYK1VPP6Z%$JfOAEr@& \D'rGzN+C0=+pURiV\ O歇yP71@G?0[#u$bc 0ʊ,M,sڬ!` dvř4>;)\\gL.\ S:p#?#}9kn{bv@'W3JDWNzZ[ 7by n叨Y;؏zw[zF.@8c57ʿgԷWƈ02 N3V,x .riXgVΨ2*qoT65hfriZKɦ L V5XêFjqC-Z _0hjPM&L.<,I545j^J%# n D3Nj fbQA5mI>&=RLL pf:f }T1JMIpM`aYOV,O?jx' Ri3AK;`Ͻӱ|\N*R1ZJ1ku })2j(ēH7<5ZL 'oBakec>6TE)4 iI⡧o jQI$~m}?!~l[EDm 39\ Xƍ 88)kȑ)MRٖ1XyV^d ,goQ~}?0hӯv&]nALz5@2$1Ln܉6aHzȟSGAPc]XLv8lw>mqYtKڌfK;k4d3 q&Oleu $8+5?0Iz9sRu WYBЪBe5UK^-WMr/!L+4d<5ey`F/8V*޺汨I &@&Ed[/r:ր?4JaC5XLEn5;>#&z6b/i%g[@&{&" b5[RMh#p"tLt6Mh <0h`jGz0J1;y f-1A'c_h Ӈ$P 5Z'4VNL{MhU+e kohvb e($FITSG@v 0Gj1r/ޫX@luvw*LVy5:uXHҌ]pPAXNn=1O};2`8UJŶkMzX+|k}cͫrἰ@1v-W4 񞱊.ubsnP+G$G+R :&Ɂr%z'Dn%b3M}\SZ&מj[:LL fV0Ỉ =fÐ_j@#@EɌ@ҿ޷BCB(ʞbc(U,7(&މA n@j 5¬b[[9nuzm'w?>/z'n괹{edyWz=\y=bAc<{&\޸uŎү[Vq5~"!+=[0@kĐ7S*Gjbnύxi3Yl 1uXSdVbmݞo6158%kULFk0YMJmi̤57Dt7":`+`2 TEE덝*iu1'Rc_Mb&{GmnH4Ԃ2jk%fjw:IR%@`7=fM^knHP2fԞ4I=@dZ˴@0M5+VTEM:c)jՕceZ6T,=PԱT^f{[d.(Y7Vj)87FTV""CEMBΎݦŷ4ȀSNTزj험$ԋJ&{L 5V燝?tu}9p쭙Q^\ҮEtIMh[44pnj&^ۊDbX'kmzڟsSn\ON4ӓA Mn&jt0EP _.繠wRW6*]⨠6FkXn~*X}5;5X-Yۅ$V[^"+phXg604j2LDS"kqaܷҵ\9Q!\b~\b7-=Ca(kph$m@E{b ` a+$MlD6J=(mI #h*pө 7q@ӆ'_H$n7JԪOz w>vgI0(T9b'U*^вG~EW|:V8+uf_@ku(y{xɭ#2jĊ#FUMWZdWOF y+߈}b-Y[Set1n⃺KtH" шigեV3nysI q[8&"Ek`'X*lN(b-' W6(N b&9g4{GnS1VN 2i\aqA޳U'َRy NML>)qM%M vjb1)=kC 21T$m @9hR?jLD ~+t ɞ=p0L<1o U/zV4HjXZI-jI5=MhD t@0LSu0fid!l$fH%17 0juG5Fg2:k!&9&TcPq14l/=u[2E4"5FY3ȠkI&OD'p1@$vY$b!K[3!S7 f Qp#4n  ;b  @5$AT4A ( XhsA1qVH&q@1A+1Ͻ ڙ4(3SV\ް;YU.LDW+XOVtu-YnjkRf+hs]eb6+BƜATzzJՠBK)h+zP 7QI4qEDKmlGj4.au[vZ R"|EdSR+*1q#TIHauA:pDh#^#XGzkf 3A2ޜfb>@y2>Jܲ!"'S湯7<+L9Dr]sׂ_ϧx>z;tW?'3|ןxo^!y[ҖCOOOwkoc/xeDG_uןyh+o5|n~G=h.Ҽxz*ͯdXxWl۵,L[>[59֎Ԥf)er%$qSŶ-LV42$fkŕ$aVbSa~~>՘cJVj~8jP0iNִ3S`'kPzS%sH[ `ucdԇWf8bnm%+SZwP=%~I#5lZҧÚQt5Xpژ6u55~V*}g?`:mJ@SW{[y* FjC=&jj֚cg hvC 3"NwSC@hہkCQ0֤/$nȠ^L(y[6h @7AȪfr^rM. @wO'۵"OXwLz h8QU*ALTiAn)nno2kYT/hIf9Jr1 NѓZRm$Ѝ$vHCjD,TT5GD3Mj\ַ9 MN-x10Sp+o,oCXjXeQƪt9ӺzN^nNy_]_ޛ#ӃӁ^{n˩m5q5Ž[ {jn]'=*Z MuJ:%McuitsT,cF`w,40*х^&g]KD~(*"(+>Ѳ4TVhqzh657s4j-d:1c^'<:y[։@`㨠&B%6 /J96lMq}? IM Eb &F3#$QA[LVLP5.f*E"$Su{dQbq[tHmLĆv O&3PN&D3FbL%SRh%Dʂ( hzf`ↅ*Aw4^rMtHAh$h&04`m XS J,6dlPMb1=MZ: cD1Tf&h`hBmjh TlI=k(W.%~a6A" 23@8\(< P+4S ']M MEcMx44xAUbKbͱs۶+E2 WYEMrje2f(3j7@'Q[Ɉ1ލ8Ik, eqYݲ'@A+b^A:f)h`[[ubr /9PO3֍ALsQ+vsFJf<@"#hVPC;FjD!('iXFO81A um T¬ =?n<>o%C`bo25*֔tNr+ᏁxswEo{O Wq4 MU6Ljx^/$p/۷h-iέp4Z'>.+88gƼ6Xh5!eԑ1u^~W?۟fKm4bL~/Sw#Inft(m+j 2HfR*nfի>ÆUM2Of+Z^ۤbƭ$ k1CniFwZRIc`jjq5Td*1.{浚:jUT4]?sF X1VbG jDٷSjYAP/ b++ ֪GFZF;?<$%WޫBQ LnZڀĚhtf |5kkl|Tر5)Omzf&LZ+?0iڻ0qn"j? Į U0'5P[pH m艠Wۅ@?ַF.X MW5I$jh9͍Vk`sZ5츸1D-H5a$@y$Sx 3Cfk[Vq >oUlh$A>WAee Uz[z_k}F TLf#wDzDT*?ERMX(ӋkAKP&Zɉ4(,AF+k Xo,7޷CA[bH !on6L7A4ӑf[x +`mZl΀("-0\EH"MgdUFrkHHy[Whin>բh0 <7Y5ZʯwÌj*و`<5K~j<,ѝҌH{Ͻ*&TiqT=:T88keya[\U`(B-#p Q.eu5_NnT&*s[ #b󦳮 ~+ ʐ+.v"EUDcy'OYSŐ; y8ת}=LtJ#gxv)p6c𯪭 3it?[ԸAZ犴U&(4/pf&h*>> w4h`dEG'`niUt  ,?5:sMjnScl R5a1KlP&+PGj6 $N Tfʒ#>ąf;$ 6c6Ӓcށ`sF-+{QH9(CnIu6BN)hfYT b6QZ ˚36`dV0CFLȊ!gtT6怃(+5mĊPuH RJH$F*h> V,(M 5ٹ*czbhK)AW -x 0O1ҍH@/ GAhEm8t3[ 1\cWl;U51 Gt'PIH8m m9LnH(g3U߭hŜH Jt)V8ԈJ֢nҁԒRt֝KۘR(jf ]xf3w4zѰ1*f+b+^o\@zAZ`6H I8Gz3SU$wQ G tA&"(ڰ>pS3@k1EgQtb=bLzOm2*D#E.bk%ҍɏɠNLz!2ڦ5 xb㔘&| ?Th&uf>ky֊7?yw^WsT*@3SnH|К\֙6T =_hVۃt:q#/$H WzG=l]tփM;O~/u{ݏ>/@^tvRx;xp^':淋W,ktn(UDw~~Mڹl DZ'_=zg8%u;#sp;W+'Sh@$57i482sQyKjf+I5>֥ki ٬jFfSSի^$P`jq3SctkwIYF~ՍԅH3Y^+F8)Lbdz=N1R\߈[0 .h9gr}35>hL?oH`w|4"DVb] wջ mZl?5 #ڢvyԋ,AXMm-zѺ-2jDekJkZ#9{>(,3Z/Y4'jjԭ$ЌxksE9m¯(Sڅŋ;f8VmF5n5BDz+N#U5{N",OybI*--'o4ڿg ιnzf]0cڂ $*O K]ކLwcj=?7fjk[ NP~(t&ѭF UhT5+*qQ?QRHUO9iֲ3:)^bs>3X8pzѸ$MyoAZ:ڂY4YGZ u,yA29kFGkY+>\NM\_O=+4IxE;w+>b #TŵƦSNJH6 j;g5-UѪt8*^Ӎ[ @2'4̣fIl7u9>{y4[[N ֈ3Dh"4s'Pww6( n43Y3 sMd7Iku@ya⚕{h&w&h+\oBL y# 2#MWh1[[zJs VqЇ>3nxiY78Zg6ny*6wO+YQ~l v7SrpUUx}z<6qfN.nj{utZT QOھk 1P܉j pK(1]9uq_xM|iHS_K}3,ꥹб}{ MThōA[Ԓ95,%'}-bEkmT*xڢ; 0ߦ/P!( < iʀ|QCZ]ԩ~Ê M7*yljXY Q֮€WElA= S ,PR`QJ{*گ3RkRܜ h>Lt@7^{EgԉuV1F*W &(*='? ,ٟz [>[WWIJ㰫:}< Tw*S73?z95|͈un[r WUc4qTJs$EsnS޹X+j-MsRإu"Mj^⍊"8(' #-*F("l4l@ @h>h!" $?*0DQ4 ,DPDX3$R:V -"("m`hN/d4eEt Ҁ7lkPE5 )V5]@i6AO҂?@"(AԨI2>B VLOCԲxqH1T(^nZeZu պ*^AVnHc?#N+s[Ev5&"gTC>j]%bek[ؖ==0ClA"sYCLq =W=fMs]%A-j-CSןsWþxoi?:=Oݻu!#?yk־+F(" N5_O-jx DqX; XhWS-c҃vNjtɨ[&Mn'V턃ފPhZN=34:Z;Q"9VqF0ɦr4R]qX+mQ2A8 QUb^LֱVޘ)  7BؠTB-`|4?r܌SY2C`W$(FuI([恙$b-olGgkR&j?ֱ̀ܚb hyb⎂ jH(dj'^Sn12`*Gu(4%s*3ҍ%]L"UTfI LO@aiւ$Kq`%@hl >D%H?⁀;V&khR;TnV$Q\Dd՘ ?4j,a&IԆS2i"T&fDp+Of&(ăwA3VI98&3Fj. FбE%nf4Kl~՘+579Sn zGZ`Z;SC(x,Hi laUmf.L\29(3 jrə9&ށi +>Qh1,f8,Ga x0Tݍ4e! Jeq EZ~hrFBOi]f=bb[RJ6ڰL2?Htt=w AƴI{WM~0-:VqZu u&A8YfSC=GCI[ѫ6?x{~}FV yCu]tZԆȯ;xGh?} n}F1_3}?3kT=.ׇ?c>VWPp=S NWY4 ϵl+qT$/]tضQ(؁Uohm0@ 4e0#چQ?چ"F +ւ ւ,}QDP ECG"~ku'N`բM3[35@n3T $0jAhN*Cf@+) Ʒ<֕ȢS@$3BqqڌAij؝PF9Vt"LQ,g)"79Р(~q w P&~kq-Q!!}SHp@@E ,䰭ĥ18Vlj4BEBVx1 Fݱ+T00f 0N;b =R9} œqTBI+ h++F ; Iϵ>!(?-ՍN Ԅ>(%qFm[0$^rWKds8^[^/Z 4s[& ȭ49f JA Gޣ'M;_S:zixztO+J2b=_3.uyotdAھ7: wm`_+<;yo[5/w3~Ãָ;*/e*4|7< QdVzKbo:;^f=>w}~8}9⏻[;m_eg1>q^>muz^st47'l=&|?gQ??S>{=>W|^K|s淋: o# %q\;6˗ D:׆~{gV$|v:Njν5c ڦ^ꅡyV|m~z࿣nim s+,j׆# F:Dɦ51{pŋwyY`" g58 5Gl-IpgYԖVF0R++ Af7Sb(m }0wV\"@rAJDh+dcapn[;{P,-,5U=N;kcO yBn[`ߤf)npHb&4VQ#OF(.Zj[bAleYǼį#ɭH* vI4+R?ނ՝>Ƞ=0v v@2Y[Ak5V5SXb ֳZOf 4S}^dUeg#5.&$lCP&yAR K٠{P^sw1&ލ4Vgln1Oq&x:|32Hܠa޺NXMӐ]UkZΒՏҀa]',NC5r< a  P*EXҮv)z`j`{Y$^-RZ3HrҀ/jvɠM`D21F P&TI,[OzhKj61DR[?"DI V=?4Ϳ oREk.@ZEUhAuk6p&(j @d4QM5:Yn P{CAQۚ!$w>TgRPP5#m^f-l(~1&f:I5\45s[ 1@;";AQd$PѨINyw 4 /6(nA;jXbõQ=͸)z0In?'n1M nohE%dA@gSϸDI @ fcS #M"J?+5+U;'Cf2$Ƞf4vXPD0 4Im, QO{:{yjӯnjx Q@[ ɭhͽE0 f}p+|bmy`g]v5L%N( O9Ey%c[IV!N|2t99%~`y%ϪoōUGP:_yw#]꣖[xzrt^?,ci~\4׋~ޯ.hor,o>4>XT P#k~}%~S˗^/~ƒ2O޻{wy7|/]kN9fnPOi^~d_ƿo+-q5-`ܞ&?z<'sy|N#;"xevАo pg߃q:֊Ioq޸w}W/:W<_s \{D.Zrj=?[O}ߨ77kJ׌KMMMjit?cmjh,3jq;7olbđ4\MZmpqLRmk1[ԒP 'Y`29]@h8Q3E+Y[ej̩`dCO 7'5Ps>#LVd) <)MZue[KV'͝Pf$ -0jpki@`Ӿ񞕢-ZʽfޕIhh d惢 eyJ߆ d`zk0qi 6ڐek5 R)O| bu'5Y"ph2ȓ4.4spA&}h*Zk0S`݃1Fok kJwP`*&0EUݽZn3ZVR7[!AGKnàWI.liPXuV"]',Ԣk}s"@xhT P*@@b*,V(kj$T5I&r56 ^2+$;gbȠ Z V5Mb#o- iE d&?< fрI45Yh7mF(; UOQۑb?G4֩9UT7&0?zD<DʡwC^F"*dM$X,cL9izgx5 *Lr+` ݪXeb{P'Ve''z.xy)4ZwC[ I`IQKZ3gn7Z' YcT0iXmӊ}"05Cf3_m; `K+A*شA, hy5=#Ha\nfN s+-Lw 'f'S* G5\ߵdpZIeI H#=/<؍KYW.,s]/j-] ]H"vC[tԇ.GFwo\v~E۷ھ/3CΗP3_#xENGPX`MhbPZx'ڃ;Q,8.k\PWgf4` f8PAQ3@+A^4Q/ǵvrwv-0H3Wt^$Z_-mڪFVއvk6?P&f*,iFMt]'!k:WLa* *@T P*fֹآ"kiM5 TPfE&Ϫnn։8Bkd4Q$(6}[q&HDPb[gZܳ[r;93@^G4[qFT́[#T'n̞+`(gV(" ,E@A#VckTWj=+0g8z`̻OP;QEfFޚ4LֱR2F:1Z;sGEKXZtMGN愹B @dMnw nt%TS4#5JGތ+ (3V+ݳ'9'%ZՌ_l( :K{O![ hkO\ulq[`($zL zb6zf״p+E7wc'3AYӞja4lnx?Q}H1M0ԆMF4<Fx[qz (IASke斶"ku׃)'Wi6W~>Oy#~Sr5= oPc+'WnO[,y+}8%׽,t!}n|o_^~Os̾- /ԑ/TjLt;=yjKe?z|uv|M%tp0ā\jh辤ĀOzXkf+>GO㠏S Z6!NM[cځⵅ* wnpI₽D5)=kk4 7cTgb:VFbqƐ15zυJ ZcKE m'xt:?Mݤ,0=p?XtTQWIٱhQ]0"H\Ԁ"OVXT P*@T P*PeV6RE5"IQ-cvk,Ԫ.+0ȬʀXEy0z2Fy5c=EW]fE1A%f/޴;4Zn$[vjtU #*=n[ EXz@M"h[ 3Yc0 PT\k>p²,c7S+Y\Hο 7*ϽRwKl14K3XhX 5Z=V{@B>+ڷLV}SXTU(˻`䜏zN+@?IfPAi }QxeT=.`ls^/еm\N;>E91Pq!Uƹ mR1I[;kIqLjʥv`EO mv.f \,ʎȮT{T\[~0##`}Jle f6Q&ŕ'n+y1ZNGڍ{P}TF)߱GAUwMTԑ-urZqW}H..LtxoytrV-HAy5P햠:Q!?4l5JAPhH'@تh9"%KP "($b% Մ 4 h$Ih N29nnJ+*E`.emEAD/a@ZUy014I %I4 $)Ps9@{I9NP9"zQ%u>պA'Ԍ y&(c{ѕ3 Z@w{ՠLIڂ lFYe&pDP8*rXט6[-ޭ z (!q=(=z@ 0}kM;)%:Q䉣H HD0 Mh@5D~ku$V @DV+4Qs>Ռn2 Ѥ,LL/SLތn} ${kDɭJUVzVR엕IB:gr;ј* U$j ;c&vZ~( f-46{ ha1@SnD ybv#vhǫ_l _ R;'%PRk5. [uBFZsA0/Ribea1q-Ҳ/ sI1 f"ӮGjSVLp},s&QR"QVaQW2sW :q\հʦ,>I7S\,0h=p:diX&Q?z^տ(z~4G#2U_P! u7R-7Ex>χb~/b}>?=&ۉV:ʘ ;i袠TSMZiM3_\ȧW;W<\׌<Ʒ1Gwy%ߡo .(b1jUt \/ĝ]||̟nxu38;w+U]O35cϓkR$o\.)p "Xhi7Xc`kGSEo1y#ڱ[ZlM 0|OڌfހdA2h@lP2 jgIɭhnKu4&&$`g&[^Q2ZƏsTmZuXkkC}jY-rUt"u *aZT P*@T P*P&jp5sDDGnjp5s1\F*(&ACehH3P;&h hBkB&(1H;EXw;Dj2Uխ`6ɷ$AҨNp&Aj̠33+1/q|g.ۺ1 z~kt 5(+իv^bHЏnV\*c]wsZߧIH=kT.Ў+MZ%YwMD44hZիf&@jhXM/N& W4èsFqU 6h89q?NLLEH>ǘKD?V_? .j&>fE/NA F8{OҿS']HqޮT=_VrOޭ =g Fk`[8)#DML3Ckڍ g6@MY`~Q т @kɵc {3Hڀ0XɠLXARPmlۃڂBفS0;I&69bmohhBeę#[ [i 4Pe< (A ktE&OO(#pCg/ӥ"SAPGqQA5h[46(j"L.x:A >4{`7le E-b Ȥ* {ֈCN#^ s@%(Y$aT LTҬAQ$c6QDb\UbEd+4AϨ孀ښ"b{V#'M@;4>`qV08q$ FdkmsKbR7sE$=D" ķ9DO35hAk6 / 3Qf9FiI4`ԋ(.n%sh"b⡁MȐI= چnԌѺ"/jRW0Mf&RxWp֔pk5XL[ȱ"nmڷ@d`j{ AڥmZVo4sgS mͩ08 {LONƢ DN*q+68 ~!v&%|0X5¢ŏ<`wOޣh%"ME~RMYz,d3l9t\35ï=hi>e0Ĝכ|}/@-^?kRH,׏_W1?ݏz3k^>jĂ?5csF*wi\SpzRBT AV}/ꞧ´zdbnU~ƺ/s|_ӛoxNAGu?^^O~ֽ_9:tT>>9Z')&Rc}/?>ϟ# 5Z F5=^/'/. W|;n⼝syv<ȓyVXW-x1j~ԧp$$?ڍ/a{Mx=@҂S~bk/ꟽfj# } gTI9 &h,եކ sh)f(*]S>ՊR=H)I# Wu-k$F'56k;Xg"Ɖ(/پӃ55z;e/ b[rո (\s5 oiAnFi=ۏBLod@ĵl="PoJ ՋWV*X­ *@T P*@T P*(\ Qbʹ Q`b&X"EE%ATYQEH[ , `uM21T!qҀn:UHMnjAĤVTe6IRxic q[GBWNT犭jH}^F{9nuzVh[rMJq%\LNsߦ+""ە\\z{tʒ{\\H7&@h\z_oZٽWۘ=Q7.ڣ5* 8#8jw_X7+YRsAhid4ihHoZb90(c?XmI? pSʐ׌}g%)p;fGYʑ[cAK>LNHٍ|[&k]FF;b5/_U?}El9 yF@Nf+dcOsP67T:s+0爫>Nj9%%c5nY5B/b:P h/#476%X!d-P 3"(؁@捨 D欨0406Y4P~X*=h ɼcVMj jҁuԠX4ecv"hKy{Ѷɉ n-l.[6#Zq@p;;"0@ P "Vsޑ4 miq 1FU{'޷e\ J9-렃) ;UxP,D rq@2VOZ8 #P@0Q-2q5eGhszNި1MB[_VL_hXv  =u8h}x5[OE?zu,}Ox|G/7?SO`'5X/{ձ6 ^>W|o¹ʕ Q@k J֟mo2TZҰs??m2_pDIQ?Ǜ8P<'ĭ򭵦+ <ZW7^o+̼ Sm_c'?j׏7 6ߗmIRŇ9"_˛{{s/xmý|o'>sU̓ y/6=a}ZQcPGsF~?t{44SRU\ܟTmhkp>M ji~s pdG;^3n屙kbFƮZAjEzklWQ5͝Y#=i.k t5 S#Y;N8i N 4T+0YqҘ_":NtG1M421:a @4VzWO[g4]{_pYlyb3eH7e1v$dɃoo=ͻ Q|Ixcz9ٯ=mQ{֟}串Z@$y-}&{ldpH9:{V.p7&:,c4I$ Ո(.&h+M+tD V7ͨAdQ@o&EZZ 7I2i oqM{QMd i/z9A.z3)*XjC/&+40@'5MqM 1ށ97<F9A1Z -䘣0J%.'3@@>w'eISv=$T~b Hg(-rm+pilL1Fh S@( ͌Q'0h,c"@FI?މ9cr:Vl$L%3xqf\T.ud%@JIE%4BqHRcGZiW9$lGnc>պ@=8y0&RdT'mI(ӨX#Mˏ޶ *$ q@qѰ؃ӭi?lƩ$*ks՞+u" iҚÀA4Ix':(_7e(:;m X+=$ڃ4vMd,]y2*t.`kuaMljj'{Ui|ɭaޫS#5ÅjN\Qf,%q5/>j F,zQYN7c ] 8ídRf~*lJ݋W>0?3\Qb͝@S\,@jzof^NOT*8$Rz/0L]N&o 5^jV`r T^ N֬ 9}377,Zֲ05bi3W>nQgƍV+Ǖ<r龣$AW~?o?|0kdz<_>y[u_W;,zsOtuu)"4*Шͦj2wLF@X߆v<{M7#1D_G~GU -7ZݐVf:x/?>gN}g//-%J&6pqS=gz2n#M|O/]8R϶M:ߚo׍*v5od{;lV5guvֽ}FOSkwz{VӪ¹{5tT\wMf'[zOUz{}/6:SյHgX Cs[aF/Z+5&Rkn]֧sF ׼4;@b?'9_ڢ{^J{Tz}  a3YX ff,[HLĎi՟ 07V4lxzU`=݅jmqZ6m P\l8XXq%]@ VÃq)UVPT P*@T P*@T *"*CTbPX`hx1*Jj0aENUAFȔfCJF UVUxl*fmTm m0JTnTT TY$T`jVMs2J`4+h*,[/W0qQ`hZ}+*zy/iAkhc@Op>hF*ɂ*fE=N\EnVoxaa%x*gzf3>Xq2N~ZU+(wԩ09keH/k2?z/]BTH14w>ʤ3'&me\zd@?9}W-Tؽak|囌QI_+,5;{+岧gŮϢGˮU#9]øh3Ē=ZOݲ?zzԕ}^X*F7^\#5xgph5GQBIѸ>J\b"A?]7CA__?5#~ 37I WI^\ݸD1c+U> :UYll]P+ sk>8aIă'+OǽJ^ǡzk~r-l0W,@ kۊ2ڑ1[]qMj9[4ֆl^In[?z `g "n84(N gA?4 ך+ hsd DsT+%PǸ-;(%@(N(Ф[:H6ziܑS?ݩok _y/>??lxŋCz׃q!u?P_>gb=EMߟ,~`58 Q b'@H}'9sf:~1k~aYq™5_ }2IWx2ξy(1_'\laj`Ҿ?~mNc71\/.vi.hk*tk|j=CG5q5E ژ-Y2WF+?{zMk5kn1{᭽Ml nkq/qA-#C`ڵOZs+1LR-"8 oJnژ&0sXjͯE[OՄqYxy'0|<45*YM0B0Z]-YҪ՘ nȜVG*C&dU VA1lUhUl*)UhUAU@T P*@T P*@B$E@jƔMM DTP{ 4OZa7Jp&@EXzt*N-Vp"F *@BT P*@ "5F(raKSE'U\fM DTsI@?*c44zPF;Ct +t2I6&f&OJ0+C3@ `TVsM=+@[G DQwfHh=&D֘px\Hҳ5>@n1[*TdMV7{vZ킠pC U-wڼ05N%VG;l[qɈ-rz7-HWozlo[I'xm;ʂp*/ i0W pp}ޫ_5P!;[H[G#o-%K\_?cpJGRo̵ ΊW8AMsT13\*kKQxAs~A3wZ,>)ޛj ̩hGS*GSSl~{b5IEcu٪k9{rx`('h(WlF`OhTo[`uv&Aj=" h`f4h llM#SLxc4I@h#Uk5 dQqCCjO’M3[0$Y!$bi21T# PA ANs8JOڋ  qĚ3LGiعbhC=+`#\FPn( [u4ƣdc)T`wđF`N䘎{e[2`0 *n+3 OJ 3MZh{eXNkn 6`1@w *c>n7< w5m`S #+r#bk4!wb]G@"8I &@$)ᄙUdڀeVH${ Kޮ+48L4ET5h:gV(Gz3K@<ѲI1B}\=^ܚn0}f䌟B4rqF@1Qu,XzN f-oKn\`wޫ<`L onbU@Dˇ{SLJUHmL Kkד] {HzՕKR6jcQj]M5BY8e]Gz\F{2uK-$zs[^TI]zȦv2Z,8\!؊_I W+oܖQ.y"]!zsQxth|n13ܓn4PO=U7AT~h֕\Oi~ύ-ŀkTs4n4l\q5iͻH |3sLSu$s@6D։)*554bCѩDu!liUAP*Ъ5A­ *@T P*@T P*DԅSU ƕFYP*@ 0UĥUU@T P*@T P*@-\hjb˯ a:1:3Pjr5FdZ8{W܏!PV H6*2hTFXqCZO05sIVr+@L{p3T+]OW+0X3;`vhuxz 'ڶT&zk VteNJ[ VH%[Qi.Jg /7aq٘p3'lj})ز㟹\,PqYVW[Bz TUC{In ȚUum^L+-޹U p9Rw N:Wy};ιoe p }W?$SnӬ"}]jh- %lɃզ{J1F)>բ &KˑF(AO02XqDg"aֈAѺd 30 QPhfFfDb&Q+XQ"?zkjhhDhfw]"2pf(sA YNq2+tY$ukC#k(PO#ލ< TJL | wum1V.~14UXIU"9H%r'U7MFE c1 ˒?z^kf;c=ߖ&9^\d``>R%YG7 CՠF& Hn$&ǽkN#cdD Kp8X&f@pPhn3UlH,%U20hV34Vۈ‖yeYw:d=l6}Bޥ c3VhFk4wqWYœh2>mciAMf =LI#aʨ3׽^&q"mLz{VQ鸼-z!lk|tC[ XXx;s@xuNC!b qS}-'iR;ׇ<>*.@\/[fOZo+o{I}Qa{Vdf)QfCYnxh 1kֳVL58R g`fixu[h^#S `p#3FU94@T ZZJZXT P*@T P*@T *`sSCT⴪ZUfSSUAP*mH=XUP*ШT P*@T P*@UDhjjv$ FfV6מkL[ +?zF޸R`eOP?H\ ϧe`QF6Z$KCk39#Ioh7Z74UI+E=c3Wsh1j!˺&*s]/ZBo2k0ū 95jt@ kqK8'QJw"((^AK;QɁ5^¹b*̽ဈU{9UCZ d$ [T:Uk `UJr1UW#=c/UPf:P^d)\J?(AL{dȸ7̉ZF+<|)9=99hPU9έo.+sU+߼E?-Xv(r;r鯽?^-K`ͽpGAS`??U;[gV3 h0*P $CqVVm!h ъs> f-ogI@?+q3Ahhȣ1]@[[툠q@7"#{;nB05McZђ"R4 Vf"ēfvӚXzAg>հGpNhڢ(HP1BT5h P l PEqA$;њ)+~Ʒ5` ˆ^6H9ŋ'YSSi!FzVSmGA"ay>iobfZۋo4 aQj;H+]$UG5ޙk Ex{W*dWi9<@7N2"O޹L W:/ڱl[}FkulR ZV"" C Lnc5i5eP'޽R9Vi#3^8+ZZ]YA_OדښMIsWx/m}.sUziiy$bdfP}|/_&Vl m_77ssΫF:[?_WgptWJmZ~_wz??>`M)sOS?\Ͱ=x3ETl~lMwE|*['?kr߅CCjv6JRo3s:|[FwH̑&峸~?Eq'm@`A5Ͽ'u[L`fw=S/e{sEqnNJ޶95tƖ ̒~nh,GN7[v>F4G]/#5jV7W"bhRXK ՅYY jV4񊦜h4[ ZZJ*hUaP*@T P*@T TЫVS[RU0*`TBiU\ *BT P*@T P*@T W:!\-T10+U~[R&__`1\(Z5>AwGnVh-s[-nM1]4~`=Hd2%zkUn)EbLC mxH3f,SNN*u͠"Y35葌VUTqZK<9D߲\*Nٚi`:}hwM$3vbH "3xp#pIGBEVVoiSW$mV{BUf**W,ULB0V n<s Q:$ (XdRD!tzT =h hJ`Ј9 EbV6^VHT"4eAhDnf0'bz&s@RNX9 &(Hոbж̸8;dCT;J 3z!LV`9 t5l:6Hڊ3/m?45;l1kqOhg4V ȠWUʈvgFUA-<B$( $N@.mPAɁ恲 lLT{F,[7DJű@eX86wՋJ= |&5.yHi [kgM()f"DUi Ϟ" ;1[9T5Zĭ 7LG\MXW+)䯵t:Iuz` MVV'nUᘘY w 0a*_ h5H#4a`SRKwruyDֳ ͳnK 2'nrujA'5pԳ^Cg^jSp\STa8ۓ[صb/ʡ$D{UjqCd$کO ـ07$HVGͿ:pHob}$m?յ巡쫘јZcSF6Wo>V{w:In# }],T=$uU,]&8s\S?Yj􋢰oD6OXgy+EeK9#0bMy۶ Jl~*mV=¾Kf#d]Rч&K icZω+03'kSR840VܴSSA{p` ;z vVks8@6}\H{$t@ P };T^1"03jDTg"jON*_h]A@&LqANEla+@Y x5WG#4n1A=+h?#1jFNsT mP +VA`ְ' mJ2 4J$*[w'Yd=h``YLyhqžAFh!pfҫVf<mDjPZz1Wځz1""('d3҄1j5r*EGh,?1SVmVKjJC7j,f3";PH"nXT1ċL j@ZqEu4f3ހ6DՂ2+\ eA sZo8U{{]Ĭh "|s1ZL$ܜcVmIh-ش\2-5Z,YYN4 CN-&&Rr&43]soz9~$9Z uxK*xXۗN8 kVw'o-C~0 |>s]LJx\A&/~4>( AWxko|s,lھ8<׊c~?7bօ@5?m!gG@MR~7* ogxBfן7\u9w5DdrWy7z/s*<3H8Ӿ\η~;\0}>:\uw|>܅Ocqs =E;+׃|i5wv}Cv>\8fꭦZUkgKHb8748 'ZIcuTdP[ y2NM JhUaUU%W TT P*@T P*@UP* D05HT P*[UAU[ P*@T P*@T P*cЁ0+[ L^>oj5ʊ?3\! d`4$ySޫ'ژ%~eWF&g3xXѭPji_P{WXUyBu=kqxE Ru>Xv\8:h-ŠT&IW+ڤltF筋v%\Q,kqw|-`NE1sO투l Zi[R ֪>i3VT&*7W;Ϧh֕] 0=*1zU&e<8mTݧ|t?WՊj_1 }u 3BՃ'Zڷ@nYݏ56p`o[*3@ Oz ghnmA5 < Ƃ=5QJ413Zl`;!C (g+`f#ǫhU2̚0 Aݔ4E!}]hI=T#q=!; pk`b ̊`wm$0 ѕ#nfEo(OJ5bjId55 Z= Y7g'0F1&VOk"+۔VWVIaWjWh8"/KvjG*l85 +ii+jt׃#EM|'QC@ x]xVϋk|v׊[u>V8WG7=05,9Z}Zͥ~4լ93Y#m5kL +*Xxf\dujnj-G}/mȐk>oq Kci[<~:G|9m_R?#*/՘Yˤ9X\s ^q~+xw 7K10`\WP_ڤ~}*- ԥ7)x4Vcv~k5-/+(f4-k y=k@ Z 8*XV;Sma#Zv(v 1(#$Q5MWd40Pve==A=(*5"zQ(FIX91 d`LJ71W[cG]e@@U)a$FifZ&V&e3[KB2ղ7"LnFb`Oc7|8Oci`~*M[@U`qOz{3 ۳܂j}nj/Mt>¢TAQ5Ypk̎fZ!+ \z]8j\-t޸U¸+ἠϵs\ 5@ohw)j\2e$u$I!#li`gd_1Ƌm1ֽ|8B<^jcDsᏽu5oN''es+D*1ƹU#޼=FL\V^Gkߍ?m;:ח Z^[¥ŋzrG?n׉\C+'5gu|_?ھ9cJ*@uN7JfiRvi7 "jV9u35_Lh6WWiמ,`x6j<Qxzfי &N}; iHs p\zs wN=y΢0IZRQ@f$&ضޏlzoGw[O▯ nq SJ*RO&C5Ъ*T P*@T P*@BT0* T *@T P*@T P*@W;HyR3\xMNhGާDxE➁dž @3xm2+0Tx2"XFS)@9RGhok0SiTX:5lIwzuc=Y?^7|ާ-qW,Ztivg9!18> )5"f*J'wGjȤubo OҺA$PHN*x]pn:î+S^ &Ovs9$R DW wztzO*kO/8OJnaJ9 5[> u-#}W\Fs-\2kuץ}5M[ȥ~yJע_#Pփ𯩅{uV[ 4f.&hj1Y@7,J]E@# 4dhPM&r k1\U2>`7l4`MlUs7`hh-j2h b k6(4lA?BU34}$V"PN#  q0jż&x@6nd(@}P>d pmfOJj5n(+F8&*'+RkX$n@C42bXM ̞ho#hh'7-lJg%f+[ic<`f;PEnz'-ցI$ P18 nQ +ȦDg5捠l5 vҔFl2 ƒVh(v` PUWaV&T MzezүZ,>(^<{mNkP*?ւlU _Fii F[iM)*LKԛfCH5bЦMfHS&Zd<6C]qz!q[IltԅI{BI$SDD[]$CGcUh\ViS^ trI3[Wy<⩃ku2>)a&`VL=6L4'iE xgcSJQe:n ,ජ9-89 )*bqM1-9UcPL?MӴާ#رkVS^5k\W+{ޡnqy;83QFBJ+DVi +Q2 U퉼J>H{jA\ej_ W<|v2uCmǠk23#I6T%Tk<#Sx{lG,F>qy5+%bIzyYu服Gi5 փNIaKG|P֍r\ k5a]X`u*`hzЫt* B P*@T P*@T P*@T P*@T P*@T P*@fL 4VXmO[in *ngJ*`T1\q\z8M Qjl'5O?I~RF?=?ϰS}wA[*lo骷;k)`MPȩ?Nk1Qp$5CyesWkڱW*Z^jE6Ӗ^!ldc^#4sګ3&3.^T_?n҂W ַlSL<#>,@k/˨ݸ^`T?ůƀ,1qbA V`cy9j" 0 'v f2*AUpV ڀ$=sDwTbVO[PxCj|@%h'ҦrNY.-[S$iuMxIokk\В84̊j֊zѲ1?N{ngюcGJs# $=gFk >֞l \6\+i"ydHLz^GJR?xn#ZR;j[~K|w5|t m?%$[ 6 Hp`V`(r3U{ 4l8 g^@ "([NF"@nY#5*eM`mh`jD Q\TV0B>@ PAcYV$8Bkr(؋ Gv8CH3r یPSh}8z1@{Q5 #`nC9+?$Ta:ֈI+-Me&BZ % *QF\"(qjI)34@\Z\H+' Tw4EopGZ jI34{(+El Z 0EfT#1Zњ 8[ 6n'5@ p/'=vw\Q[c|F%˷n[TX9Aǘ/jn /Cl# %dFؙ݂xD&z4 F{HI5؅س֨H nM4W6Nj°\hI(3n,04jZ{˟TYMjz'tĊ+(92Nj[Ԋ@Bēk0d%3ȭ0x+u-Lt'MJ.3jY0yf`1ֲ# mGsM-hpdsMhRBv&s4En6g"838rpOjk #=i;956(s\R Skp$En]\t.AdW+Ur8 \^# >5E1*V̭KHϸ7[i(|WX56}2v *E5"'ՁWX1#v+q[Ns^b8h焖V5}XuŋwIMb⸂&{j,WǵMq@bb'3  6r\^L^jCz)ƆP כRfa\qsfr5ڕtiuKw 5ߏ%.\#Nkoj;{򘺦gTֱ~FbbɭgqFctaaP*0mO e +7Uoub/ OZ[&sW~1u_Ej=ck>[$[+/VqɅ#Q|1u{S q:c>ޚ(7ԎĂ߽490e&=iCENz; - 4|^赦bZZ+0'fo^ OuIAlmD|Oz>,G~Z6'z9Ic vțQI!Ք+%X0 bǜF=SʯE EuɎ+1m =*-Mb ʒb~58x~qbyUJb+[ckh>Z5`wfzUjx P`k)N69p;< SV̂[8V#S}5D/ \>Y`gWwt]_YBڹة^*;p2:ڡOF?:5J z-hm^Qc0TKBΩ_ h8ea@l0MPm64H/`Djb/7Wm0S,V*f(bpf(ks6AV噞@(DWX5@7n$bh@+E{ht1AbAXfbzP@fhU&O$Aۙ@-CzQ!Xc 7 ?z;I*nmRiߞ& H2+@ fzB%4*C* `ID8\r {Pø q"|ԨB2OFҋBŭx#eȩ,T1=2i8ad[̑ڪ%/;h3Z)n$UD3rS hKj!ND n@P@X}j " /hXhpZDRk",zVkpS[RZzjaX:k.-x4ˉ@wnOo41 VA|ßRj!+MMXLM05lO:VL 8E!Maq[+qZJ=M{b@!A`hgtSL 1nbwXfjJ쪀:AϽ4L(# 4L-O 5Xgaš-wNJXMf 2)!q9u`856Cd6QhLWf*-t Vq55R@jU"%W;U;Hr;.sA%PȚőpTQR 8[ !jƝ`uej(AcOvi?wuqhb wi;[iɮz$w:&1W~t5ZKL\Rb1 Qbl`g5;$^,@50pzW,]jey8jt\,`9MaZeTHf$",HYW*A1sJd_j>bcREOE>H;ϗMHz=\Bn K:-8)iX}:""3 Zfd D'"-mXdMM+_:Cw/bA{ʏKzϣڟI7}c_ggh[괷 ܚx\魥EV<>57b v?5T BЫBT P*@T P*@T P*@T P*@T *5:P P*tFjt5M­aPN* L D;JzlxOiu *$u_rOP7[0;j<9WcR;W'M}F<;YnQ ;V>hPn!Lw6mHRW+ҋm+[$e9 WJ<NюrG}7Q{d%wgڣ+<O48{f@?%J 珚mw:)G$DmԶk`֍'#ΗTU340l=Q O^oXܰE4< 1#ڀWlL $=F*=)=M͙LЛOMQtܞZ!v恂BPWt PCk:4e m "HbDHT(!VkuPc9խ,LA1ր&َ`'tR o/ ֧-բ7VW@Lh4f+P Y#CCo@3&󊉃f"&&j\'J2880'j8?"A8 fs  }4Wkݩ;6 IE8މÕ*nA3 Ez9ZM JA?X%Ɋ۱m>5~z%BҴPx9&5]\sZgw?@*zևvYE`Pd$Rj/qdAoz^ 5x`78XLNPi' \4jN[Ŵ ܃5@kuP^kD!X#5 #U  t$jf5Z'g頢I~ա+CkcToYRV Kfs4zkrdM& H8?MyV)%xQ5.i$In9,*u8495ȃfmh6Yʹ~+t=i՚a(')@OZ[ZAY1jQ j5gNj-Y>ƸM8T:[zMf7;fj0zDnE[z9=|5>*c%Ús& c3?r{V~kzзS F%@MZV)sì\2ڷY1Y#MO'U!G"62.mg}^ WIx$:zc}:o`1̪64P`4k-]jiaՆ SH4+`z*)иzШT P*@T P*@T P*@T P*CM`zЫ`UP*DI5s+ baT+}Uu*LzPT "Lji,j.Y0 ޾{x~G9_PT[l@$O1O5=!,?j,-oWjɼ,ʪXWŸ0L55w ͻ2AA)<\bM/[tk nN袵f A]˗h)q,2h-bk0mhlwt F+`0Š+rB` GOթLTO,emQ q޳{f} mDg"Ml_|ws{\z"1${^ԣp$ 'l)bPH厲i8+R68ӻ3Ҳ7J}H <׏HIBvq?@9=pҾ 6$lJZh3A3 D41Cw4jI5Ig8rTPf_28LzT((VUWoi>~L+60OsD.q⩘ ˓pJ2nI#lN"fbf$A fS"k]pn 0NMfiLƚ3\Z0[~*:djPg1A5ګkJg"3DS5|J*ؕ2 NHjk<[_.Y`?ֽ.=Jnfi^q7}[56Ên2=b!hgvv52=j 7nO}+[#jbO3^N$}˃OdByW֟Ai&ͱF#W:Ǧ-1E#bGZ$# En]+GQx"* ,1ËL)* ȭD@?jiZ [w(M{_Tۭ a꾑*G+u,g{ə=6P &)dj|,bW&Mr.t5zRn:Þ^4e[^ڢJ&qG튌n>[UXcTP[x2 kt\KZAl4fzb,E R= W`CoY1UFcJ;(+]ӳ#b1Mgӏީ[PzP Qoqr IU?,Ek*T3lE&Lն @aEq@f@&q!=(  5$2$ zr}Pu]nܷ=cڷCm@1Ap9nH#M0LXc40#$D{I8D|2 ځiEːzvX#CZgĐhKIOi·ꈣ[7y b}$DVkje ?挪Bjɶs=jzظ'l&jE+Ƃ$J3 ZtԣyԩDj$l..";=P99PH5=q0yN'>iC G5 ~լ\jIu"jLn45TzDSHw;"jIMFRd2-GJU qU'p2j0CeV$l\$\D jf"N ZT~h)u58ʒ'l-m=-nT"TrzLG&*ĺX"J1M0'IB"b >iEHg>֓1p?HgiPG5"$qޢ;"CjY4 AT9ޥHHNPcH-Juv)j7@5lt KcBaES@Q>9X7ŋ1+JzYYfUʛR1'R-5z%?5R-@!j8:FOX Wv rku"blţޥ85:[ EF. 5ǩūwysgyMT\)Ŕck=yf5>W;,u9Qy +@s2 X'T<Ϳү&Al5(@*,nEeۤ Q[/i"*4_=bŽI^^<-&0W͢ <k"ѥ@@in3Hլ*@ܙQj s1yO\ BS47ֳ5v1YBǎRfx~+MY[0ĨgSb&EcOB*@T P*@T P*@T TR!P$*@C*h0 7UlOO*@lw2+MJJ©EOSq osTPx5~geu4ڱu2L'Oo~O,X+5I>yU.;Ijl5gI|Hz ƚ<ŴW@WkM#tNc^nc'=E<Arɴ[,Nwk;WԿE[@8z5 "kMc&Ix3ֶϥ 8LVkI)'KAj}F (z]/$ uu="*/- V]ʪ<*ZrO7'>KoK!%&Do\բ[HI;Ȓ?jxxU>Τ\9|V{Jݰ~@lz]:ڧPkq[YA6 5$B퐰"ZM#} nBڷE+[kehzBxjFv15!mp D 6XOjqCQ6V7})b fkwa}KQx_׆xAwxb$GQ\o+wOv< $s^:@Ð=@4F:kҼĿiY\iV +Mu~a/- <֯ѢW[>ބb S4f*]@8ThwO"b>d[niY5o"sCkQ$' 24h'$68EqAKVEXr8uc5Dښl 4DY ?ި{ 3Xb7TA 7Mn5jj!ތ5%STE!hXIPAJ9lEP3Bۇ4414j7I@6lj@YF w56FSXb`+BpppTW AGJ֝tԋk)X.ط $ |M4AhA=Ꙫ:Ie!j\`3\[V7qkP/I0@D1$RXMi3* =`dn NDA 3_$ ,N{Vv 7q@4rktCOk*{ [2hkt Cb*:f} s֮SP%sBA|h3&yg"Ekf$VOidD'Z\CdJePg?5-A,L?v! sM>dOc S٘3Mjw)"N?/ӬgջO9oFOĮikųU9_E+(U茩 XfxŴ) =~Cj_}.ѱ9v1GsQ ů_ɘc<͏DbMMԃc=p֧kM.@ 9b}I%oq%vb;>gW7#W\`]r4'A ׮G*zP^ո^³QS45qO|@hmXO5ª>e-\|/GhXc91u~yLr1%RД$DWHj:rikxD#֡ހ߽MTMd;rQZiNp?z/}wqT ~* tӹzǠ%dFTMhM͚0;ի+kֿI BT9L5E#G4}:"7Vwqr_Qnᶧ9ڢǨ5Lyd|&+f֊o?WqE2;{5hbzY+z~$)ևr"ktWZQ V;N(\~hp8R T1h` j6fqMk5-o32{E H`NqVP6KdQ]:sAQP>w2c W3Vr(h!qJ'hk1 2EќVi0)VdjlM f(TPRFiAL@/4R> n/9(=hWNtdd -F>S2f yU]0f]؛P4yp"+p;z Z&A?uڭ1U1`9!uPGګ]$d QZ3@eJ5cլC+'hI*\1A5KqXU+ [{qY&&)kLR@15Jhv"{j '0N;BZʼn&*EY"k4N1&IM,*G^jI=&ãP=~ZõR8ԉ` $0cڍ+YS{h5:0'&5$+4ąTHLZYg&N{SSF4޳uBef ~BIhe=02{QB[b7aQz55Pq|}O^=%ϫ+qzP0s kբQy[M{i~f۹{uM`H橢\ ?5_lE5spHu ڵ(Q#T3a0y[$ b*L;DTH̃[#N+t4MP/j,h=-7ŷq@3_W?qWՑ=hT MM$sȬDU5#g*FՕ%WqRZ(5U#^nKlRw1`p3\ۦ>Kq4˗EkKGLGCYcq'Y~$BK,{U.[&Ek(WA`UvXL749WlcBondEGM (YcN'E\v?0]Ke󻫏oե'^նL'+ϥ}uSeIV=, f*5܊@aZ"h@Y-" hb kچlPDGJ҈ #4.f`SEKOO)暖v# wџ~Vʜd|88(j4[qzPa8\U}8sȭK+[+z}#Ax%mvX7[`T!} <=ATzV~2@yVt_Uj1YA#+%zӿl''D{TbLjm!bGG9=F* s?ְvb\ntZ/KMŏWh. tP3X(&;@5MFrGn3f(Gk։5%QGZC&WD4Xێj{`Q^.,QMڌA*A`@;h R>jAf(!qMhP&]4мX 34kGEZ*ZbHCnI8aH@(lͱz0@2E4=蓙 y&ƘgG@aZ v{Lt@sl4+6ֱBk6A2T=YT93[;P.?=RkO AMmv{U^-zZMD~ձLbf[GډnP, dLDʠŒ:f M[;WrTp%Gہs$_@=g4Ox1?LZv3MJ$8wp&<պë9?5AY[aIjg|p*L*/q$7P@$qBd$VU0h+, >`ҘW7LLT_T` '44ڼ$R[z-֚ 9f' #P8('gDM^w/4PýZpdi`}8&3U*1a^Ry>ۂe[H[oyf( nN>*p#I4nA( [Ԙ$CZ :VY,}0GYjdFӑɥz[Ml_՘_,yf&=r:zDQx0uFkb-Թp50kR8j+N퇙7tSnWo7طSA:K̊WBʚulj*=]g1WiL]N:,u)MH5ڭf@aSw4, |1F"&E޴h o^GjjR>hxz4fjU*@*4+B =ZWZûfw޸XWMswZEp3[SKy uiٵ{h FTJB *@NL  5j$W uȚ|b"©+j[}XTlU]"|Ok6R ,$A}zOpYRp+[C0BXߨ.@bVsǵ~qRpIuAt#meAfvAT w 'ң|PYaԢ)I ?s_~})goә}>f@fGċɬXIUx p"'gjП0}ȿ獅չQ">kגY9%f!/@mE-[1wqLy_uA }|C'nA,Y]|OJlj2=A{DϏS\v.[k@ڻFazb#[*,%d 0ۢ Lf@ց&1QZ`~s6428"ִ#n,޾wq3XY mvxk_f-"#omKt&xMA#"On$!$R5k@M4e0J/ p5ZE4b iCjU/Mh{C>EVF}fç'e "c5PxcAMTf* GX !eJN+ULN3 kPGh1xv]@惆ߒ%yE8_weCqX3dS~?р/5}=Tx{%^>Đ}ޣT@R4@=g*qr[[FOk ڲh~Bn5]QꦘžְUE.A3uLhrJ)rzR TQ{sb2DP'ɊN@,A'?4eWhfA7M-o‰l*$ kUIް7wJ. EkqR!2HD@I V+H&3A xbăւZm X汉%QQjޟsd}U(#[~  q҂L[fU^`Jc*v֤ b5X85L ܙHmt&MhCW>@w-5@]ItN~V^?5,!dz0 qڪ3tk+Mpn"!jCpG5#P̳\CPrhOhzјTYNܡ w4'pVbk@!"(*(STnuZЕeF`*[挢Z`$NjLF&j,Mhp oU#I9`V1Mjh pH#l2œ՚X!O5do2Njhj2ޜh);am85!qsY]L u g qچ" fDVQGkU$Oz0dT)ahsSkb!{{7S#CC+ާZYSINMCt`ERQZ3u n)W;!F#]"kf`˻ ZTu 1 3QkL"F\ڷR%n=*W5R,'5Z,o?a!fhOkOJ1s&MkQ޷AC[ś`1 ۀVaTY$^ÞqT.m ni5QIuMLN)ZҿOA YգXa amLFiIsY .JTL {V`YYo*pЋhMM>I3_X0@v'l_w廤,ő\ ns``S4?RR+&:>7ؤVayJSY+1F 1r:M_5;NK6= yww%Ӄ4TYT 7[M0L* պfP܊nd`DsRX0f3>biyա(XUUT QT4*Z+m 3a3j?L#SVWI4p*֕V4 u^5*T P*P0D5Ǩj!7 ns3 |7:O3% [xU b'#+wq]Qu„m"NH?z O_g̯"["ĮUZǭjB%HUy>β9#VQb$+.>gݱpyT?_}1 [KLwrIZ2#5_VY>#K @ܟjjXlt1;w8/۰uGqr}OH'8ڹƿnٺ 8q5wnn28nr, vW5Pkθ >gQOIDu` fֺ_[n.(#+]d}۞evWkW8Q~:W*/If=&81;_(8@`-fZZf/􊢆; \[B zXAzʴEZ.He?'>NG{jX"P0; ǵsZ_? Ϊ\' EEG?}XSP V [i4R-=QMn74(#4VD-̚N})@1AJA'fikuOsZIAZ  V5B(ok eK SZr`Vi(yA1^ւVijUCF(PTY Wt(֓(##M)MVe+S2A(wH0}66x5zYVE QDFbQ嬃UȻy9${VWn Ju @m ǵVzd3Z=B }zOzJ7`bE ,S[mS6=bq p5FLB 4e([`F!y.;\jx u@fs@d*jkuו-W`&VM1s;#O5Lh],kXRdA Lf#n2 ԁ'Dm""MV[+`1Ql OJB zU-ɎkSPo[HX?Vba6rjX#+.EVwv45N7VZÓ'#fRh&"",^:w0yQ[0I?@r&;P×p}5Z*jA`\3ӇSAeĭ Һ'P9hXYK/ohk4I_`DʜA'SU [fVs[/tÂ"+aZzdt/qZbJAn=ہkX*1J^YS33DŴVbm=PŋhRۼpD%qkRz 3[ zSAnT"LN ׭VF Oe2j`ذSZi#Y'o&HX3jS+đGQC Lb~hanS1'ѲTEXWN"P)wژI̬ {ĦަsQv'\yN&-A*=Y1QyKM{`jct" ۩7Kuku-ұ~>2TuR5;J"N;΄Sӡlw%/ᨭ83F}8-O5х@mn aYLnMKLT1J`Ux_zi цM\0ڜVn@+0(3VQU LTZVMg-W+U*hT P*@fY-\7x5c xGחb<#]W6/HU䌆1^gǍS.F+|~=c\&}k po RP;T߹F$l?ƚ԰"~åH WE ƼsOr۵0Npd3b:_㽻MֹI.p1WqU"ؐW,S|w+@}Y<[\j7.3@ F&FgBJ sުxʽ-=w;#I5Hcp=>-z1kMu焳N5rD7JKn101"=;N(& >@`5Z[T'ZHd`H64m˜Zq\{iďWSGi{KZUnLOhbb 4ӐJ54P5r%&DQ>%Ijk -ҵZ$<bL3Qnph͙FhMcڄ }S r?5Z b+R{F0?/G4n()f;h(KI 1U+xS)5g<8(ݷ=t^@@ VJYaj,q5kgۘO\XeDt/Ӝ_.[l\F9OfUF~(=}(91bm6Cs&i\*xw: *AG޹krFUA%a}pzZj|ͭRp"-~]O(t?Q;nup=\]Mb8<0VcӈLPSeFU[ډUhMk^Z\A 񈊭\l?@`Rhf7 h!r=jW6馲ACe fhA*#ިG]bn4`NN34c [N?KEhkLv1X.#h1U8TI>բ8PR03T350s[Vg1jMn,9A I`6wb7'wZ"nL:iF$UOcU x'ZC?u"^@UАPi@5!] Q5Ec3%".LO~ O@ McӝPx_c]M v 36 +-0"vv\ ji+O$Gڹ$Ѳ 5*'&*45KW ֊qf9>q1 4*Ӄɪa6 { ǽEhk &XW 2*Ij<MJMh)!b+S-;`n*nV xbo{;,]fA VAպ m~k5GsU+14V9BjpOZNifTN[ m4T 9bqޚ d>պEHr=t_1^ C7 52˜jE2qXT94N$V0E`gWnk1%%aDsĊ$seJlVX5. X]@\)ĿYbCQS%, 97sYj"dIoe)yVz yjjl9= 6TEMի1TT;Γ R:H(463\zya_/wGiW˨qŎR&}^ߒ:ُu5$2GZ?NS"HTyt}1#FbVI[o'ޣV[0;cCO[iif*S}.eqFsÎ(?0EnbBqQ}N1d ڿ * #"Vc"N*K;Q*`IЫ fk!.0>K 1k~0Է`⫖Jo5`x9H<^Uղ{Gs\ 64_Qj,\Y0\o*ס?NEωVk\O[#TN"LoVGϮ-QYRо?4?[j Շ&ib`RIjOZ1N휚 l$ ֱA^r~6@[]Ihs!niJy-xa_f%[ Ml 8bIdwkGx$N>ֲȕ'\lDEcQkm&:`-zRCKP < `b0A։5Vc4 9>ղ%OSs̹TpJQ!.=FOnx0'562I5bnj#Rś@0 I>Vɜ*<|UjʫZT̀f15a2jmj;I;Yƞ=!%'>+/uBn]NFA //*yIc":@׿x^DW&ME63@,kpT}(OfT{p=QҚ5 G4Ԓ4A &E4Tx|C3UFEF€R`Tb$1Ir_8W(ͽ! nuZ/ITeu *ebt Ur: ?Z9o-L3Tu{-du ?z4t2߽r.t-ïO}wks}ܽIܞ=KBX~H fO.*:ԉr!F. v\PX < {O_N&(*ܴ;gލR$A]IP sT<~(r 5ɠkPVnL@i(rk`d86@I<d'`QzPAhئn.ڌ.vD`m?҂1(<?+`S{K7VJ+&{ !X4.fcVKfzV0+@Y%<Ҩ 88ֳ[Z`; y4)hT'^Z"S 5LjA {Qÿ tP#24h 4жqU7S`$G(2blLshlAI^t-N9Oׯ:GZ{ei[Jfh4pk}ن`ESí̃ObCKjOc H cڷLYq'ޚb [m"L1wqj` <R%jق0Z˃Ux@SLH\6jq=`fa*;e9IF(DmqXԔ LI5AqRXDbYvI5L8>FylD?5*@Fkt7V%`h Xoa3S@J`V I&@ `.$(J0\}Dshؐx3_ްH|l]sڵ[;F=JyUp4L[QiGSC1?Pi)޴;q;d<,ޚcՠ?n[djA m*\A-4T*(>tnH5`bcfa*9OY+u)i&LI8$jt:i{L0Z!fh*kt2'p8Y^w@Ȧ26&bksE X@8wbk NjlILҘkzĦoi ef/dOJ1e/s4 qY 3)a%£Yj,fuMf:_A5cv٠Ss\ANj,IR=)LT+S ip+&Y_[}dE1~1S7 8;H4bIt-nhҠy5iVct*EaP¢JP*@MjʨjJHSY`j P ZT P*@V9O i^.< ?|7ێ_%A>&o+v*e3z#>#Z'pf$ɜ澏\~+@*I G =pַLKbTjUd5 RЊ1֢O3XK!f*}1ҷ*#Lf0S;jacǤkXֶ3P Z34H&HAj*}F}0z`}g#@asT|l8ZuE`V49>F-0";hNOosz۰zwoi kkh\,GɊyV/įB ;%z7}z7iԯ]υ}cnR5kv$ֵuR}^ /4H3qC uU+ݳ $sVoX]V9+5h7ES f>HWJbh ‚,@C5M&*q Te/1Tƒ@ǽPjO_z;抂p@wԦrlmV Q[՝M̚h@LdRFS ?4`9[arnɆ8Vqjf <ʜ"f$ګL:SM0bVzSS 1Mf_əb{V18 4Pi%T)ҳ[4`qi^Aؐʚi!Z&Y*on)$cN$ 24H.bhA@RY$Dc0@9'I\0[M+,F 5*0VoC\zS< ! 7JdPHIO⊉VEcwun{+OE8JPT QTaQi*3D-ZpAԚziVhyЦkt=nUVUP*@h&~~%MNs\<gVC쥘r3 ݯW3ǿ nIf-nebs$z7L_CbaX]"9>GzbL o7KqFO** Ֆ1DH9j2Sb94b^H+>E $ oj'Jf+\{µA!A&;U@9ִK~'> H['梋rG\|V-a%`P&^,dV}@w r;UD)mLW##DTմFD=qӻ[[-퉑GSzm5d{nb&ruMrGhD=Y/=D@EtMM`jnF(Y`hy S`ұ/F7C6jDeqkqANKvT{s@I@&kuI[+1V`>z%f)Ҁ yTR"=I f(&u bW3X.B"YYZ \S+W5R"jq{FPziLoVFnRoR }orQ3su$0 8~KwHH'Sbz+ۊ +g.\;w~]ρkm3ӽf7]߄}p-.Wߚn // BړApˊ5[@'Fkjj{ k,UeM4 5" 0#5DJiE]6}Xv1Ҷ Ϡ5B#f g&P Q(vA^l?#bg5l[hY65nU3@sU wfN1z2$jBpFG5 A2I) `.ZG@;e6b b8b*B4[[[lUPdbZ$ Y5Z -Y}5ﮒ"lSs$fl[A̜MV q> I֤oO+}(YdgԬ*nPOoQ-/ުVba{ #h'2k82 ;j,9@5STs1ޯSzĩXCLRfIP;SDH=+5eC>rCIC(NꤞM ዋ4W>1X#mXA6:$DHbN#ln+YDE(MF#,++MtoR04}4;q9lE3W,L7X~+bj퉵@TFޑRfՋdԃ( 4`s[3zTGZn+S!mSl$<⩲GJn$8"j0_5AM1+kz`wui9<ŋ`(ku)$n=iQַY%L*lȊDPKzV)YŅ`sTo\PHՎ@ANwDVg N m84\7'414ZyuS?hQ3[7 J1 $St*MRSKR7ј" I(a 0tk)[7X9nL012wqYX&qZb`*L8I^8bKsiF =i j\8%tˠN 3^,zqzkn]v-vL5}C0d-+qV%LT`n}V5 9 @Iҫ@Xhi9U7=B& A/u۾єTgh$"ȐM^G<+u$sZ.AUn\kLmdAbɜ( e%$T,ާZmMcd=pB HFv,}RYzURRAXgm5D\y\+^yV.ۆw5y z;%li4 mLG54כӵ};1=nWVSBQv4liTY`E;s\ j)C,#5@p&V{&ۃU Wnc ր*0TLi Z>Ek5іQ-}&@-%kՌ=?ӕrL-=LP_] J@h@EZ Sdt"N l=ZYW%$5R_<}K'Q*Hc;S&QGJrGFH{B4VBvȭ8D7\ bN'f.>Nz߀ZL&ğK+뤾VV>+lv^d)jk]&4r -cRFh,y@`W,Hf Y>5v#jW&kZ f$dWk֫b j\fH)8h#XUB""w1(*j.ȎƜVMgSP=>H r(ޮ15hTlQ̌0+I kP6َOrcºF8NpUPÂzTnHY'Z+A2*GjHQ,&!vS5B 70h#2b_r113+ @?JK'Z4m$ {L0#DИpc#5.|(8T -PAH#jFڪT!st4mɉYE0ý^ ww\"pgW)dV8+?=NጚN7,O"AJIԦkk(ja`)l=(@Ti Ⱪށ\H(j->j,bn"63@Y3ښ$f M4 H4 V[h4K| Vl4b@VLȪ[&j"pnU-AaFhsƍXތķS۸7Ë1C BrӘ#ŕSYb'JD ѽBy8m᫕еQaN֧՘-׵e]s7n 8XpXb@aX"I )znSX=SF1FjT DΒ_Q[Wu$KGM=}8-iSV *Te[iS&kqEiVaǨN%b֩UB#-Vu&~MlRx~*K5ljuj)1upgxfFǵr>`-lƫmX+1g`<3q_3׻'j. 7GZSsͽמ:WFmJ ~bR3TZ-04>=IН!47 {զ`.>IcAq`FT s@kj'C\,xoZ!I_qTʭzڮy=ebB6[3AkO =T)v|;zX8R8u0@- ZX} c۸uq֮"^ NGAZ-nA2;Vژ-3FO_ ee$|kK%ǁi+bk[mqD$_;^> HmxygՉ=kx#hUaP*@0**, *liqU40D.n0UgAgW641 Fހ'X &EH:xy)hN U[ jU]D0f4xC0sqǁ#4ŷBSZv1R9n"1RֲnpW¶T]n1kN'{Xɿ"@zd$+uG |Uk1B}f1DY?jS}.(80`Gbʀj|-GSceg=E7=A67uM>C}Yت H<:|KURpXj[<#a}D?gT(ɞfmhǨMo A1 bC.1.9?bKHh<] P VoiU:9_ocUF1{SR֊ց589`JYsFVKD{es}iO7&?zY?ތsT} hoI)ւvG /4:$qZ#:leXO(rfRpdVC`dh٦m4+u;1 fW(E4fC 5bdQhK(-n0M4H h`ktq3sp?Ҍ2HU(%ZYBHC‰5ZyZ2d郇sMf$︂48 9$Jh$n2ha)!F=bs PGpYku5rc=鬰gMHS+EgaZ'7sN)b[T[mG'5>Ë}f20d^LOͅ>V{^'iIw51S/1ScF0A4+j[fVY]yv0՘R݊t>NYȬV"iiScn"ו97AoEJdKENҥd/drHubI5k!y3xq_FEKpatr+1Kjpj, 6f<. bk(zNsh,JԕXrʤ5KsW7uhܾŌt^'6=]|[iCV]X1_I9 |3yɎ*UYG\u2깹­2NFbٷ'+(;lՄ2 #3@E&-;H޵, Aw5Bə#nd{`N;&F(+޶BHlYSfuu dFTնv2MsZեrޓzʨ#qM+'^H=β5@)J蚫pIRh+8S#ⵋvGJTẅ1Cr?}5Ŭ[Yrt^k Bu}nRsOR+s죊zPT P*@fYT [V)IW.sB\,'5"-;bBf"ҖLmiqLlp$65Rys5"~ L?zH `}B&ADC*Q:vf ,'޴WO01Bl19ڝ>*GD?Uح1sE&:S>#`yd1xꛕm&*ڜ6ˁ+1ƹeف3S:uebu/]?}cL$,ݳ}టLP(Il&!]B~ U/!2VNVyXqZ*#uj( @'ތX+~g[V` [N(rijיyTT4 E&n3j jjhXZlJ:IDk(w{SRnIмD3Me5 "+4ĎH3Nt5ڒHvtGumAckj3>  PzIMހLsށ8+޷MQbd2vP;QLy@ VԮ 3H0 V޵C?j";UJ\(\QS08zC R?kuޫR@st3ktB`a;U }t'@D0v A4ql !|[M 5+z։$A 8m5 m1HT*s[MTgV A DC5'bZ%2fA 4>`E *tH6Lܦ`LK4 w0C1!#k M=*9qTS3A5R8a21M1 7qT汇W&CfiA![d ojqM03TaՉ5m"/'&ro扢XaNiY&6b 1}Ƙ`rLf"fT!* K?1#nvIX`E" i?ާA&v2rkŁshz8ƉR$TEʐ3SbKub>6Tb%<S"bWVۦ`W#uKQ{p&MV+Yϩ"Dj+\{**XO޸HSwrcjrOL!u5ZrMt^/$zk[}X33cpOSܤUaR+=OcUr c?c!fۤ /wo^:|ga2,]Ug$iz{T|߉s_O)SSp33+]Ls  t9j/:} TW<* T P*@UΈW*Uʨ\s6ڌ =0- 0H l3qQcX$AC+jf*ǽd<*6kgb2&kuPk\FJϋ( SP爇 -ІQƁU L 5zS S["=W|iUo 7ȣq~ҁ(ҩYZ"bBYn5Zc*($ 35Z]@l3Q LUAsԩconZ41(鍊J ?M% gpacFkRoع \V߫Ӗ1Q:b뿉>eOr{ztcreb}'5uH}M=R#Vzp3ƫkct½r*Sv]j+")~ Pu 8za&t(.Xނ9.AZQ{"ُz+ܶ jlUMdncZA1[j6ФbT8*3A,sEPn$wiPOމMLH"=h%yArLGފ K9zBz۰(HG4 zUzb 楸q̑CjZ54I4eӰJ4%Հ*Lz}& ҁ0f4e:(֚kA9$E4Z@UP$ǴQI4`ON{HlM58[ o$d o0EXX*&'&MPgXz V@"d aLPķt"AEn$jƐSfEbDX~ nED$jMDMۭf^ պ:Vݘހ怢 5Z.g֧c[Z H46%?z&\~6 ms՚H ktGqqښ=Ȓ{ДR).ўlo0j[7 ֎ܰrá{d{Q U 1v^qUe;PXi{ 0ku8r\ `f$4ՓqOHYM[+yMA =jX'@=@i"IM sFX|wmR'4ă1ZַD"aȕj:HzV酻_ x``KF&H [#ڰu挧fܴ kPKΛ5Ë""i)1ַAV@qM LSnja&L=u8#Z za1Ҍ@L@Mh&/0H4 +0A"MYYqR鞔1 KTؓ9 W,j,n%,$V&)ls딭y\}DYcN'ay6Mf7R`:ᨻ07xR\뤊RɪtW:"`b yv'&h\Jvc'"jƜ3ϵw矴^u-WwZmro$Ǩ6kR*@zz(+ϵ|-.}k7%Fwh_ҿS'}? y :VG;@}W/#Վ9S +=EeKE2Ov:kDDOJaI6܃<*,tuC_v  5]W@w>lo辬c׸SkI j&l¶7PVPdQB9ވ;8ɼV 5ZHz˻qFUwUH#FT*\Y{qh`u iҫ@[qZ䉟夘5 } .Mb Ȫ n>kAg4c[ Enڳd5&ȌV b-jf( PA A`ge7myP nMwz6-&^WaN162j `b~jX ͳpzPIns@[k o1Kj ؒ0D և"+S0D]bjNɅ4f0kYIYTz$$PH^ pń@OJrW*I +G"J'IdUʋ c]:0&=H3Zڊ9yXAV@9RAN ;U lkRawA%$9]fk4%b=+4XYCEA~+k @$u j5CSqFAPQ{9aF‎Oz%PZ$٠:-d" cFSP EYhpEIHމK& G\KdA z/L>Рhoڀq@SAHI4@`h0 e8sZTs@BrwڴIh[C+tIp3ֈ>Z1[MH4ЄH((gYvIh$+R[J1+fy'1BaA2'Sւ*4բksFac I}k5h?f  i,'"ć W3[$ 40PCf*B%E5bEj6&t"En NOjbbSDFiǤghhAҚLbTuqy p3ȦH\qh hdӃV18I" 052N*E;S-0jpj}X^l`p8xf`ϵ=ZQy+}[\ U#A7jW5pks\-w'up5Ʃ;g3QUNjQ'n*Mn1ڻHc^.=V6ڽxtd35mXrk:΄VeKuf/Bj<5\?qwA JU|K|^[]bXFA _c>,WgƯn+1_ͼ~>\ZXyi(%'}<ѕ&TPKKqV˾&@{uh6N=QTY ̤B;~f'm7܂9F-۲ Az"(ؙ vzIEK$Y};JY [3MaTܦg4Vm~*z?MT7>®&q:γH/l aL䎕4_RW55Z\"zK͌ܚFG V[ضzDx$`kpLnw9rx`꾘uC2cs\:;k+N̛v {`VZT * Uv+Qȯ7C:vn-hYX;noo6DԺM `3D*qm/jf=1 ;>2-krhQђ k֊׬nQ5ILEVZ E+O1Mkՠ&(bA޷DN>)k`Ud0Ͻ*`4ϔ€kd{P/"Nr~(#rSu*A M42Y.s`O{%A?5V/p2r*DMQ(ݷFO5LpzK 'ޘz #޵_6$3 :U1V I8A!q==&n"zB \I̥#ф@ >7`HǽyD+&4]0\YA) @8ް:uy^dtC޺1; Z7 9'ZN85=3&mcT sTVVGހN"+; AmO|SD SB$@*3415]3LT`'`jR5*Hk,Ezʱ FaZbjyɡLQz$IVFh"nx3Ԥ1= քSO-UM \M `"zNp!b f60$*i@PDrEM&5&4R1"#nM|m$mKp5:#=h' 4 LJ +t>ZV Ej ?D0QTLjQh.2iDXʠi%#z۞k4+ M1%0)6WZh`̊k13k~(=:\$fk$1=w1%Zwv*,J[ Y!`bpsoY0JD- cH/[A)\@XWIcrrsk6G5H˶I5`3:f3SZ"ub^bm\Ӊ=yq^EeslYGW\Ԗ^"k1~Za_7׽įxwF&I ¿a8ziEnlϖT+&N/1 }hM~sln"quYq1&`.f SYbUHU;5Nu]*1$զ^@lH6 zUf|P՛9$Qn]tjbaJ6ʕɬk/ "tO1atb$y0; `j1BlGUvʽ8dۊ,ӊ,9Rb7A>fJ(A+N4Z_z.o5&0/#40 n {i@\9 Rk~h(_wktVjE5zъʉcw6T[N ΐ;`bRVCYۊYg1U)p~ZV~ȒWfj|8U'sMn0?O cWrX Gs'-[m=R*lViZڱ Yk*n\jo-Sh\S_]`skKoP;`|?DGR`R@'?4#xk`KhA&@K4 Tg41l9ɯ[i7[nfzM7 w(©IϽXii@eDv0; !#h[dH"ATNp>Y)8OތӼ?4b{ m2xKHۻVX$2Z&F̊3UWi#0hb z69cU*p7wōW*,@1>zEFev dҶdubwX^v}5,ċ֍EAV@IJ-ͷ` =h*]Dނ$k՟#4-h/۵yAL0]D/OqZ ԴKd?ތ|w!ѣ[;A(;DP-( c(isR F`@ɣR f+$Lhs*tm2fMLEnpMLtH ~)Sd֌Kn5 h;4>SB&)#g޳Dw?NO5D^SC'hV,uYNdEf} D1@H8YDLtVXF-8&A$ SCDu &9oh&^y8HS=u$/jf <ք P9&{hdԉ"W5JZ&S=+tF3"ndBCRH~jAUk1 }IOzf V1htbgjNqC Vc Nk,=kHnaVQj r+T Mpg=k\3dr*+a4EcBa8e1I]$Mؓs`)=ˍږ5ƯD+/M`ךTFaMhJIfy\^}J3mI$q_ΟďW-ûO/\Z_/X#R Yql_E-~}9V\3׉j,(PIGSTf-Qy 95OQwd#SEH-iԈ3UdɭhKd"t֋ǽw"hPD#:z aV8VQhl\hOeraJ 74Q0U B{UJf_.֭-mY6WvWЎM He d4bGކAphE[8%S.2xf I!wR0hgUnv3D}P+9ҫ82fgҲ &>fb7G?^3:6Eۋh"w|_u:^|tst9/:2۽3'kӣ*X.jHhU"\*6ڹZTL?MEQp+.vEFC5_bT/w1^@^ZW Uh*ЪUU*QEgT *ViDNYU -TMSiW;Zyudi5ʺFe0ɏCY׬dR>()\ґ37A0(+]QX駥B:Q{~*hmD@CV;kiZ$/h~E;g[;i: xR=OުV2>VLfYYtE jk#S᪎Z qV>m78k~i8*J\IYYMХv'jsLBKn0'*/-jx_1N cT^U?7(oKQvо\L{# {QN`yiN4OqSDYd퉦"w&)JdcMN#S! S0e ԞT$2+t8Pv[Zb{űDDET[S@S)Vցn&( K7 `Lku[K}[ z$O%-?G^,'wv,k~>nɆcVbY wW J*Lҭ5h\b+s}MP75ufܺ;kA2qT@u2aES4bVLQٳc$њ n7@(i2Dmhŭ=m5KEq;LjhŁc9AnxAhZCqrLR, 2c;S $z )Ivq =Q]wUd+cWgs`GT2>ت`IkSad59ڨ uƯpH1A *Ӡ]F:Uc7Kڵ:#j$v1kHļY`bzzctv5 =\k>[i=[O䎒.ߵ, eLq?ү_kiN@'ںӾkH:z*eH SDXxVXiTX@W C yLJES +}DBZҮҭaP*P*cp#J[ӅWmT}BT #\-Үv)_pVcp86*VVM+YB YDgV]ғ"`P +[N+tdY7-&UuBqUAG"ke fQR朓*[QZK;WdUJxP' Gb*,g-V{?HҲu^P*̽y-܊x ~GM:ϣ\ ؽD~ո1u ցɴ38®Y} XGu8ܣsh0A&jo-QV^H I1 A#ވ3[A`bӑ[ XN?Y윐1TcVCh RIhr{]?4J3# n PĘцAkp~OOz$U)z [q@GDPL8a++s&,jPf/I[FTVA=Þ=$fsڳD]Nk56 p=Ė z2TdHk}Pv(]ONjUh/A ?⭕0E\bqz U!B$Fm[<7Z + o&Oz4D]ŒÓᕋF\eFJI\h($\F3Y'(˿4,Uh5 3@U2dTy` X( >VPH$'Tn9BG P!0'F`UiSA< m&fn N5$3S 83X@uӒ83[-"=Y,2[$S٘c! SI{պA+uLfLEȭ m`["mnNmqXڪV&43 ĽfCAh~ A'`V `f%lG_rcsR#? }3 顆WhafĊ簩jIޫBs$%)JiS@{V fA7Mf&. X4SL1}i$RĐ1)ISZaha5#kV4֤iX5dIZb[fX[ă|ATD5Ehf c$58 u EcD,@0054G5:ً`TRAv 8vuqkB\YkXW 6?j HcQ$Bqֺ5*POzrӥz֗q0&sz6Tuų8צO_<߭OjAs!9_qDK,uLcO=޾=y}oS>|kZ\X N?qy/xgCOa(K9p?]OWa"6NQc[0Iu eJX"#G&~wT!S#\Hܪ1&}SV;CC&qډZUAh,!榋 ỏ?kGOl "ڠՋjŁ#Vkg VX/ Gh1R"ݥNާni\"?jJPbJڵ6QUi\@-AW+Z2m=bSYte}YV!\9bqiV{l`.!yX2gTBAި5ó+Vm&2R Hk.6-\ɏrQ 9Zw9M㚕 I_FWGw|TO}/cnlF@Ȋ 4'ahlh If_Vhd hwHdh M`cKV$sրO͂O+`F)WlMn+:q55@ؘWŜPI[>9$U]wQjQDs@pZ7 2#à<ѧVbkq4^ 7|V8(cq+AՔ)2fXt_OP'iIlH0e@h=[)b!#C۾30B, Q[ v.iu0ǵTVkIPN89$M =($w ;PJ+8lNns$cBd{P,tGjY7rL+ b͐]XTA($~h&rLZ O $gj_OI5h!;k.rˈ+gɦ&1ާ["~T9D皝V$qYjem#2zhqFkv VZZM.&*u%9k6 m8")Պk0Dј;ؑ/*&k5B5ar@1`d~ia581(̑[@i"1[ypj!=ojY2=굘`'G5cZbh5aɪ֟n[jEN +C" 3h4 bDN3Mzh@nNg#!~ f޵\5H j9a*1 !ktÂMS+EPrcķȊ$x։:3M֚sD'mT嚁67VjLMD`E5$T)4:Ɂ ^ahy2+t>F9@,SD5ZbwMF#ċ֠=' 7sV1\ X3EN;T]ʪ"[ss\'q5*0S5. (ʀm]#P\"rJzD iwtdh9G.TC=j,PSMucvs#>-Ʒ8=;Oo;x'?>ݛ#`?/S=|o~gfb6Ȏko/~^KLE˃pW8KS_UkW:;̚W9MvUoQ^kEeX$XT1cJ:<с%ǷS[V-;a׽`@gfךP\q4h]SMp&> DE.2OEv0DwR,'ް `HI&B-n$~EVvKOZL2c5Qnnd|&5^ޑcbÍm5g{r1Һ2[`Y@Ψ[kߞ*>1ZFMV 112jW-ݰ M*m@ǽen5.^Wtc$^~п'6aqQǨ~Z,\'1<OUaȚsZ ʌPÃ[)Ӄ]%,Jk B P* @ -`xmf=hT VUUS P*@UT"DW+jb¸nZ \ln\Hv.UKa\՟H6*[LLQ42+ wN;Vϧ PSȠϽHp*7ԙE]?8޴?EP-1#D#wOf=NV'CP& HHÉP`t GQ*ѷ=FnGL[(ȻdY !X0jxD)RØ4m;kE WlF;3/xa &31DuKnbl 5815>m;qQH'"+u 'thcTT}OmzQ|'\Y@8αF~[ et:/D5|%µMK^(.@#k( @Yf) /jnhO>ibm\B VK4AJ7lc? ϥI`Odts8V E+"Ǘv'$ F|WUQw'q!i&~2&C⁷?j&6@4F}Y3Ncژi $րK:"[`Iv {V#j=ڂJA)@֝lM0cR&PGj4zIo}F*L.b[LkylH?:\tDe|UD$Z%lqV jKgyAzv""s҂a1,6ހ7=Y=(RRۀsHs(Nc1E 80 x1ۚ+9 4 ,m=@SѸK;Hm[%8D(tCYR`-1vΟQjJZkIꖭ1Sի [۷ڳTONYHVh!8M-SL:%`d-pI>KnE4Ău0-iz5$}ƀ;ktk02"LDZ'2*uEmAh*$E1"2 VF\ۈ {.rj)]dAprkc)1k6xn޻G:"53w7[kjh\GP IIEKibdiS^5YJNޝ_7-?MZOY7fT;G?_BZ"gjW~{-`=e͸=YTUulK^i2bDVI1uUkTɮިug稫sm홎tJJsFQDxBl|(š h.i˶OzmٔE '56՚5.t=4sOI5=n b^q 0$5&ۭ xP3z?9eH:g?A!GAZʭȷ-'Tc#SglV9} n+CW`+jp+vWy8V;~*5cT`jZEEK1\ |+JEhx-jUU"SZ>R0E\eIZŕxS X1,+Uꅔ9u.[t-W:1?XW C^|N".5x*dI-|^+sįms,W+mAQW7*vukosr\kj {ieb:#]sxuں:Ԡ6õv tt;Br"k@ѐPsVHw*vF ɈkK ϴuZv;`0}# ]5^  lIPZөq@cӭ1L1e`NEH qchVpPn* 8V M""Il vk%JjXZQf3mnt؎{IRǺsTN-R8Ny@ErxhjmքW+'ktVw(=itj@ܓUBƞHo&[;|2(lioFYeGw?{|/}>+]5s a'#Y7XG5 Ňzcu35iu5`SҲ(ztSr fP^M *YSZT P*@T P*@UT"DW+W+b:+k:Hr\gjX>RO5*d^H B8sFPNXg4b' yjP-g@gP!9TnDjׁv&6%oi"m,%ҲQuY=4Ql5}LՅo¤WLN焨nKIɅʀ[ydQ\h*'nO$GLfj(AYSYW|TEnrOhwv#h&FcC*5@*ZR_;XW?EeGZXa>n1*pe ,8KtCb;ޡUOߚ; . QV[u͉1SGST.|5#FƃSMpQkufҲ8pT&PsC"S> iHn+i~hwM4cU%J޾PPz*وqtzGܚ0%^}Ͷp$(F؞HW Krx &2$(@sUAI܀ԁVIA'#o"DFHa@RUzS5q 4UL{"I3VH{OR$ bfL|QJ ~ZFzY$bjC{UDB0b?lJXanwZ&, SWX[kj@zCZI[NtX4t"55ƚ&@iJ'm g5"* V,A0rfݲNr+5K{\K{W;EVg\k4Ȯv֬)P"2 M-մ5 H4@@chޚATw҆$2hbJ@9E)FE IeKek)k0OQTӊRt {WISk0ʠUA։L+t0J":7ܴ0[H 3M `MHS>CLB><*&֣7M izjq0 XX sM h Oz5l怴 ZA!Nh(Kul19)Pk|h`Y!-$[;Gj &I @^Fo2AMYD{#&f` C3A3m5fM4$LZaIHocp@5-U@&"C-E*P;7Juc9V@ڂD+]b"zWx\ا*q-Tc~d]-umpzn>p%}jlfU `u|4Ϗ-}Y=z\»L`O<]czbƬ[rf)"@Y:2c5vtG:01#2 t' h'TEBc b)ӎ*LQ([TZk)n(˴:cR,n]穩m2GzZohnP dmځ*rhrrB}#r()gVfpan9bS0;U!Z c~F(+ꮱ T]&Ax Lq]"Y׃ 'azZ:с]1dɪ\n.X 0 VsYnhL+5NOk% dVtzp`_TۍvFOZ2m q, _>oHXU1I 8jǘmuWM&Pt~Otqĕr٤Daj lA]'ƟUmpF3Sh,?5c8 gIT2gSVJ3N \an ul")UV@T P*@T P*@T \UPPT1kUuwWc56iɸQ$@$2F؞IS,.(1l 4jCd?=F &a ~b挭> cZ @p٠ḾAvݏ1F3@FVۊS·1~Hdx8 n H>}G;~&V05^U2h*3@ OC"y'*_f3fJ)r$U1~I^(3x@ h2C/l d0)R}'ƶN'Ds{. &Y>#obhQ|sY+.Yy_TwRhD@ uBʳG`%N5xob^uT`cLzOx\\8j/+ ^@!ODUkU++q^1U(xL|B}2.d\TfU?j1 'U$z 3qHʌzJK{P 7m;`6@3ϕ TWk|*ՕbET;"L{y%yvl4|^/7z)v5P+x%jƝV#35 zq* ֺ'RfnTiѩUT4ҠT P*@T P*@T \UPjêW[$WjnR}aLѱY{QMlp>( 6(3Fc T"(cYl$t1 :JB9h@(5aeh4t2h54WKcvY(yk(wJ ZjZKbX]⩊Z(1u)T0.xdVL h 0Dh T4Szxi VԵ&6RH>Uk/x9ny2Ċf)Pn':m@A1޷v%Tq59w_ # qҳtws3Sbh\*$z<;} +{TxWk~·8*Y_W[a?ޡNEZC1p;AuEEzŸyYZ :i 쉜Vi].@4-#־뉞MPޡDXP28#ڬ!DfhˠqCH9` L#s#B{lց l'mihD$Of =hʐM[7aA8cҁձ'1&9 #1!phaL"X fX@@ [~1 aŔDU }b8wjE$ y$`f/q4RJ>$P/2q@-B:sAj皡~lhZ B:'pH41D@ԀX$j"GRQYQHѳhQhAEFFR6r*juT։XԷ ':@AsFadѩ"ViA3$ 8+u&#ڂC(A"I2fl"݀Fa BLUʯzbqU**[~;WYR \kxb-ک @Bku)1'V74qUЉ*C`LKD6ԇPNzVlE`,=^պ%1X$3@Ť㚡!"3Fa0VbHOZ1)(hNf(hf11YPȦXԷ F$zELUhЙ`4t f#֚]MaH*TLYޱXx5 XYkq"w@1u HTHFI@v -ڱAA {ղkbN6u {Mjcɾjh157ǥG-X(I~O޾1}GZA`AWγ1BXƹWH4JD`5ۖ.I*{L!Vi8ξ&9syWD^e&H3-k7A'59~c8 Dsj{'*#n2IsAv#ӭBqb=9y8uEBY:\n0yUNH9r{iZбrA966m2WoTgZj@tV,,(sSAYo.E[~aoi2{oy3Ldk%- Kr:*\&LzXm>MtuQts#?ؚrk]%2+*Z=8aߊGGʣy]?ҡ DoK-'Mnu5A  2|Zܾ }WxΞ [c$=;Wo,/>k}s~1kᄑ_]Y_''2_֬}= b$VgxdwmmڧdԲ9gKV8q"G\ӳm$F& _O\O<ܰu۾OeZ5Zհ3@ҡFiQE@T P*@fM B LT*cp]I x@Er$d:@^b~- kހֵy?j 3")Ѻ fj5Nfuz/7*Fٟj1s&TU=WNߴV{ w|(,#@XQМHJZ]; }5F9 /@ VHHN5,[mCU m]);s>A^ɚ*\D[ VjBoVd{ nxf OUhwbpXs n c?Qྣ+VuE^y ?j -_ҫf"X|SW #cX֞B3A?9[3O *Ď~UY.0;A0OtDoO3rQxGT6ƺ֫sh?t:0_R74P%*4驭[K3|q;mLS$n!|3L !Ĝb(;ťG3!m?zҿ а)4b$1 ִG*M \ f?Ԓ(TL@z i\])$ӭ5 AlM) ֍N2;"vؙ0beSb9!IEBroL>QT(H35BXGPFԁ &0)rh =^h mCzE AlhT]?Q3ǵM Xĭ @9јrOA'ކ&4jŵ,$EzaHfQj:{2"4lY1QkWޑQWjgH"(elKD4 aOϽ@}'ځ:&804 Q)Q:X ȣbJ4h-y@2"+Yml+B"Nh8[)GޭOQnzMUu7P3ֺjBNjB\ T2C'p5hq-DcЂ3"wnQ8_fn OZv Z%s@XU NF(ј` {ĀMiXNsXa1"} E|0A45DVhe}48YL(i$ IoL&bdi3-̚hc$V05:$ u4`evsX7jqVhgEF1Ezk 1@ڳ@VT[QɫeM&k`+n]f`g>ncھR'x򚷳\. w]'5ڇ}@8KG*ۂf@5:-%pkzyll #к *3V1'U:v*rTkN&h--&~4/?8@.dQgU!m,=EГo$3 =С;qDyMmy!=SqB@0?ݏ]]Xgήk52LnjaޤWH,X`s5I`f*HNbӂ_'?55Mf,} ,9T*:ܖ,Ţ1 faIw@9%Ylxi;W?6,[#(or`t9K_݈9EoO\jW\M -\`F:X\ ԺiY8`j=hT P*YS 83X=CJ*YVhU:iH E=h[tF\jW*)Е&V=EdfyxsPmԚsZzYֶ4kFƬ4R\"y874*#UI Q,#i0᳈'Db8bŽ)U0kv b -G"bǔL\$qTe_p$ZYT>T5 \:AlU(" >6(f|15:$X-$c$zgUJU Ob~+t/x@@F߽T1pdj|0}#4ѕrA1⭘ͻXPh35^C0jο'2)6Կq;h1k~lX9Ѭ !cjU05~y} l9sUr߮j=[~EDv4ߊs}F5xO޲:Ms:իsl<ϽEkK vX<<f@75XN6 $DE\C }!lRڨ8yzQޭ$јgQPîWQ"I#J"L9@_4?j2+pf"q>ipADOތ9e}r`76 jk4 j➞kX L ;a @MS(ZZJͧ,}굘PNjA Q44O橇*Ք+Lk ɠMiDn&R ch)nYѢL~tֶ(d@IWvE׉H9\hEMl&6Q#1H`7jЛ>BJPq8հ+[*yUʋ{YR ]Ti&DU놠z4S> ( Ѹp#40k4ASY'QJ :8A=rzHbTAqh1Vhyjpn&XghSڂ`ނ7jn'{+'[^i*t;)#ښdB*u=4#kՑ4Qe6i)4ĞfوE4;&OuSӊ0yÎ{H?qML.s4\ް95RENaY%pnAFӚM٢#=b 0*[ʈa)fDFZgj 3[>KO-n>s"xrB"KA^u>?/GM"Km{Wϵdqj ;:tEnkNk54-dW:ԍ/"S}і^;չɽtu5G:zdOkEe>!uϽ\EWaI{!Z ֺ1L~+_Oޤ'ϓ}Gt$ڍiL3SX1Vr@r̎(YuO=ޤ1sS. *IN&vc`r-K"uh1`b:d*u~k\Iijڅݣ7YR1v`FĴ7#qR֛Ř@bgTJlj~ = <~N]ꭸ~,xqhZT~ks ;vWSu;W;]z$=bq5* Obո,:SBphyV@p8&5@U**4+=R)* 3qSDC52H\V;18?bV#Y,3SWb`(R#9 )pFI5b YP`7Un2zQ\#t{Gނ/ xjA!xAȊk$}0H4Ec1nއ"hB$UAjԌ1#`+ѫtJ⥸ϻ8TnS[<X[}|VP[^ 5-[H#Z΄f3u@s'dVwULUmU.$q5ZzP*gj<3yfZ{Fպ3ox'E W=+tck|sUWwn9@S X7cnYF xvMr 2$JƫQ 0OXX6;əN¾@57JW+I9#T&}Sap^"FL4 dg?n*!Y?4I'׽Ējylf s1ր؀q{0lIp}R&c?jCzZ g"vnh&\~hųp ?mlO5"FA8W'ߚ/,*4rsZ1 әA1BBD3F.9eX>NbŻw `Un5i9j[c7 Ҋx־0V`I-ToP*oFe҇\D[r>m@ 2$c5\PV-uoO S\klin$%qm"vݟ`-1lEdj%f9]ۅNQuR@S7fȅyW]ϸr'ZPmPMX`4@,3׽¤I'>QuH"h?P8 ։ ։ÑZi tiSM!tupj=kt+y?__Gt9=z :$\[C5Mϒn3+;+ꔄ V6f3]##PNItC9 H{`zt&G:uT}ۛlzz#vөC|[PNj JP @ qҠMsn$=(-"I[i 0>:.yV{``4H#-``(sn s!ǵZ;+Ȋ&[ $q[չ5Q,iUs0G\cZ9 5vBJOQ5}\bVؔZ$=*~YOjhʌ0 \S[$svn,ݔ~*u @#gHKFgbk _CfzǍ8,eHK{맿q52XF}W?gӿB}b^@n=<|Gg.؋W,6mjVKDPxx\*N($wdW^f=&f}>Ozӧ kk{sڼr~.&^~Of߈}Cur'gx2vqnoZjo=\;Z&"y~װѿF"8gZ1Fu>`ml1@#$6b [ Dk N*=U;vTܟjx]rd^jϘ[yg <\T}'Ω_'O ѣ&MlJۇJ8 P* 쫜y}Nc=0LG[jKOSR> o5/84F[iA4F^4"{ t"xg+P@O0/ @:T"AX l҂  jϿmΧɠe[l*@tj[$TTn^nf`ԓlL!V[BK 5Z p1ښ{ @]|0]9/@ZGS۰Rc3Y_Y &e陵Ln3-[R6ګU ,ecޯLP"S|s[)_mp3ښeo'a]} L\{eY43^ X43jP q AW|H k qU*.zG"Dڠ $ \!Ӹa]IPEX0}m6Q OZ h#z;N(EXa3P$4 asaTpq"h$ϹJI $ 4DXS؁b5LШ2xA Q44Fxb{Q"Qh+\*hv'l}ի$h,ZBFB>+5鎕,Z;qS(ŜN.i["M;b1RK;zMs;6=**J BPR %Oނp5P⦉"Z[cd+jA5)m.LV(sA;c@&*pۅ@T&T4 HlGEdԄ4(M LVh}MhLae i(8z k*ADgZ]1VxcPkf8Pe'Z2hp"4M`iG"DZ\cpcHf S޷BDBhM ZGzhei8zI5iAF*mV--ýM jɒ3QjQfݽY "ZE M`p1@oS7gnL( `Vaj m0_`-dkeY Un)3`&5z$K %XTj;%0*MfKArwA kՂabMlI]1QUF|hQ Lj*G2Tm,^O'x$$"W{d3t~sPY[I:YW{kbŽ"p=][zudX˓$"!u5ΰuL۶WHpGt;wf} *qv LPX[x 5=hܙ9&E@-e>ǥ"W? 6H"D@KwQ5-|Q"ۺ(n4̉In!oIUލ_k"ADHBd(¼M[T% X=9A%`w,-zL޺kj$UD.9 57$c޲봑j3r5tQ"YgZU!X4 $VMNc5hguhCN\m[-Һ?:Fa FNj:ϸ~H6` }FF~s^5S{H$ ?|R5G[zzj֬\5=Dz`LQvdk.VXO5||֝USv[3ֻ~^s6kp3y:f 7zSBd~hǩ`щy7V% "Dz0VO &j!,)$Kۭh3C順 5a36p93єz1+h 7Du C0 fv6Oڴ"Aa@ PH+0$GH 2"9mP2OcF``"BMܞhL\VV nAjӋ3X[BR9b1&(ۿ沃!c޶2{#S02Ӵ7zh` 4shoJ0zR=jDuF%hFzyk`lkXPEB_RԗTelRjA>4/Ъf.14hs׊ w2 u9fL`<ֶRxƞ -h[ ^I"M`+~z &aE>6nQ%RO4!E{`E Ha YHY\MR!* I]b3DsF P@S =)ٌ4EA5"(7 V5 $VF2>+b*1@MDj+mmEA_;:?ruWE ʸ>bU?yw4tk/D"7UDs<ҍsQ;QZX z3nJ`ϵtd.눬A$Xj^(ѷ],Y1hCڭ0>h&N$DZܬG#40ݴV"XmBԭ\LEA+KKmVO }1P&`z҈e3 bN OvTh{5IN߭q*Fjqq $⌨%Іq5Q*eUλz9n] Aw 7|?P'TsyXR[reqPٱl:c\twMaRI\:oB%Kxf[`X3+Er^'{@=뤎51ϱ]q4{.sU&9_/ۯi^&P_ph@~YџVMx~Խ'|W̶3McsOs>ݱȚ"un/O9ZiW$8}y&ɎעwLfj=\\yCAs54N<@ɚO&fy2`0DlbQ5*xԐE"Vvky,\;3uzx]q-6yo{Ovnj}ׂO문UFWr*>ީܿM04wp+LFfj3M=6LiLDb.t1*/+ |(ME{:FGV!^f ES*X@UXlV j-L m0(5(5TU64j,"u]N&ޣY@AVk0;VXjV9T~՞P*RJP16N=zzOUjDHɬ6F>HdMS61ڦ&\Ԉym- Y[=P5K㙭;9 FAGMejt*G4uMgE4pIjٌ f`P.橸ɹ1Jhb4[+ڌ&+u<6]@k-[>ιY (Sg~7{<<לּ@<[R p(#+nR (ǵJŵ&vp*[zGevyMXi nB #ک6 /GaV SjquFVb\;"<J60;A$DхbzFP' ddP=bP+A[JC2J/CZڧH ع o'Z3BFuaGsRXRTH4v\(Ajlizި*HZP.'U pL=TlmI$TK.C1 ]>{H9,CQt QTSs*[ӡvMor ku[6\ݓ\ZGc84*꘡P߽Z+5eDOkkAMwr$H?ںHPAҷl]CZc. >{RC.`GRzľ[a[kX ̃ڃ|ąǎ DWXhq]tdyWǡ95èkx.e1^ŋoDD`3LEx"7M\T'f\Y9FcWM?IUNձ'9LK|t80Z-x+,x8?^~6$.@-w{ZѳaWz'^twk=-xj|_S/-ڸ2kX|x5(Qy_?#ԻKz(ifz4TXDMsaXajkJ4q\T*iV'Vl *UTYSJ^[UƠ\" 4s醧W#>zOX*hm- COFV3JT4;UԂ&عX~#+N\9=OFBݏJFXԱ Pi2'SZ65P5S^ \ p3T[Ώ!n sTcZ41FE S֧݁Z ښ>ymIt D!9EDٓ n`I)Nj 2X5X 85iA$ LA 61IxZRf6 I\$чDnOހtzfxz ?4bsI%$o_S*b9Ņܓ]k8/#iCiI4Y#4 0aOZ nUA{Ol`iT0>EҀ 9P lKuuA(n=[]:W:֭ QUEDW5A<[6QX8%ef XaG+0у$gJD J@`VPeOԁ_6MN]O^\6$u#ۼSnş?V Qxt a~UzǛV?u|'?xpVk?W hF}5[%w>GO.zczjQP(ϣ֨fUҦ64bYc5uW8cBu5b~ _Ckp']UAVT V`U"-s5qePmNօ[UHmU5f^{!UVwgIP+ BxP,@$$'ۢPzVdj6AҀ;>h!s @'kl(!PApH9&=c)@HVL9A+ch$P8 4kؒbjA9+ץY$@7Yݤ"s0@-J-qF TDHsA @BhʘP'*DES(sUѴw(]*vȟތL۞(pY(`֥J,"`A-2}/YfԭcE1@f/Y7ZpT{E*+$"'s=&.CB& 1(IlKl 4kXX4@TⲂ0X&(, 9{ciPYRc4*$ F$4mMAnD 09#h'o4nI=ANIVh`h1E?@bчAך(fjhLVsA^捩(C3FXr=14 `H3FTxےjnU&V&0$ Be8AjI(@4$M#< ?⊄CA4 MsYL[.*[jջGTj$~6وPDB4 3(cKq'ތ@VlAp$f+hqDFy j@;V365HRiy'pq#\ԉ[H4 (Lb@ѡ&A-5&;] ^ 8OOmS cJB'\G˟[x6U#NHx}9a;0y\Qpc ɩsU/)e&~*jƶP%ߏ3UU5h]vq Se*9#2Ot\%jAoR= I\CDљ\`чInqP hy5ޛxKh"#P[&@B9qU dOP,0`IҳYX&"y{%qvh-)WKgpFදR|ֱl&Iղ\s[B bUKjj:3T2uNK\C*I ;{cVpGQAfet=nid W6ǰUU.nX2*ztejF7IΰڰFs]ugڻH&&Mtiy+E+&v5Z+j,4뵿V1)![vn>#PsrjJ#hn>֭=B(3":t&:ק**^\j͖+zr+q295ĕ$y\!s5z@\fSbLzF5I{W]3?&;:X,n#e-׽n9׆LOz}Ysf^uڼ˯P3^{G|NWWoK k7sO#W;loIRyN_ ƹ0{ZǙ}x_uhj&kسoP 5;[ZpƢ+#Z&@Ȯ_ODO*/Cr1|{X s5 8c7LEn Zy\UIwfZ֯컾,o޼~Io%Mygjԯ:Q |9E\q] zPT P*YBtBUͥ8j;JEXUX*MT"&b& q@s lu ]c)iVQ`br܈6.U[`I{+˴Yp&sErZ1f.P. X{M3( 5[O4X LZ9w4QUԈGGHY! WR{X l?,?zVn1Ȭ@t);HhMnH',J1h`v1M0I~+@H&s'nz$ޚi1MkRajdj $Fj, V-`t-LV1CSCyxԍ6B2-13F$ n1ڀO9e +[9[Z"&oF F?4BVфՋnZʸ0rj[d&v7mvD P.G2(k[4XLVD=\ fk h jzN7 IkWGRΪ4젊2 92cb *G\ Z/S#M_0MeIX @@nG PbF>У o&y-1POU@ ҍ׿4~(윚aF 2DMh() [2eNޣژAY3Y[ &LѩAf#@RRS4 AX++Xq T2O[Tb@2*L1Zd@@94u8푌P0Q1A0rf:EfP`T[RE1SFչ#:YUP5!3q_Vڂ|3zPD^hbyc1ǚ 1fdhh"mEPFbĊ +q& >ZSsT)_@If3b%QkP[$8jsA% 5!nbI&ES"i؎l5Cͷ*Uc^4w Y7HڹMy>jR!};@jwmDRCck(n cJ֐O$ Ն.bT3Mx- k+XXtg]@ ('/2-tMA<*$K(k*v@J3( #Dɓڲ+LZ4]z(Bf/|w$Ma=&T,00NblqUXX 3r;YБ KMD4`A ]ߥ[փe۸&AT*"Ƿksc:Q=oiҰwSQ0]]8՜4&+6kO# S.LVed 4B> [^$n&D"dAވ A 9REH3@94 DrhJaCz12‚%fV]`μElMU= dgnnf8ȠJv@+ 䎵+^= pMEVSݶT<{3Ǽ.믎>i&75)zU g}]}#GPC\R@YŽ. ̒2E#<,%Z V`m8.m{vF:SFqC& * Niwo.q?5LfjlLMt L)*B_2E\e C*SIj2m1^M462Gz $@Q{T.簢bz5 ѸsڌђиPY#";P#<Z#2ᔓ"/'AT+]n,`աEPʹ@T_7.n->?IA&IzMG}AGaִQp;հVwREBͣ>k6zG&HJl "JEm#cTuvcj,,gXY w5EOuqNG~l86Z8@k @Q GMw q\tcl'9b_H}ݫ{p ;NA=lH_C!1,sb>(/(T.Ow^k+[$]s;g]es3TM5Z7O_q{v ʜ1P]%M=dE[N=8# u6$.ɉyںj1%&Z1f%IbIwʞf--@uh5CZdOsZKDQa \R]'ڹX5s\o X_-3a

ƿY_ę&gHga*d4 rދCqڌԏh&fD 8[AL*2L8bVEMmL?`ꃢ2f;0Z1,LwR+> uuPA3o`3"(ӽ z &f&d7RY@P^e+h$MRI14 LHv&jEXlEk>e^z,HH+qN ~+흸"v(+]VMTTs'JŦ  ZBLFa3=V}&d44 ,VUFƖ@[)RP榪&V5޲`#X  zʡV!)G9"EMJ¦ դ@3ަn0dP:($E폽Yq=hj[L|j>XH QI:0hyJhrxnQF:P6" fOJ $Hh"OaDJ )EZl 34np⭖+8ipWH!3ᓚ31.(V2j9q%MLw|{iC9Jm KozԨ[tȩBűڦ~ŀsΪ-YR=!|"b@s*ZCq~(,ھ$Z!f’4"NE4Hە2{6ͱBvϤz!4RXPy@u`hʎڱ$ȣ H"`HW`us_$`ns?Q{qW+ .d׫*ܱsx!\yRc|k#f曆zUjq5Zx Yb{v"2 YoߞfTو8Xu8taZ-k8mϊ*0T&ŀ 5ZQi[z=SɨHQI>~e\N34l&*0H#zfI-ɩNj1/S*/z5d=Ls*by1ӎ=ڋo\+xm녱_#1Y؏z X{(k$-V 3{<<{9FփPm}y| j:]^es^]-=EyzOZaX{D T E'058Qm"mkDUB1Lj;p-V4Ҫ z+l*TW:ʁ(7ON:JtgT^T Ҩ޺*ݿ(?=\VUP}Rcfch|AjkQd% P@ϵfc#BA0)Dz`|?jۇ6ePӋFaCQʈ&DG5,'p à4[m03o8 {`A!{H`AܔA=DM&p ҔfthUS@h$b{vB(4M8}S bgjG5H+CkqAaNhʵ H"E[l6 怬[=Fkv呏X)Z0]ډYnH1D@h,+ qU A&LYD7V {TUFޙQE)96ҦfAZɠf5"2 X3@UF @D!"N&0R4ISLcJ8rX":նB DeOWZ)&1$5-ct:Q Q&X0fkC 9Q$PMLnpj`?5 zfh$SuXpu k` ;OS*ک \&*34U#MUwgڂP3@*BT(SYMrItL[HfEI#[BũXEhuCh>hݴ c4xQ(q=hzQe A95naށ8tHVXpBCɃ4JZ"i`BMP"zMq@"DPVK{TOj(%%F*4}3T1SY5QV[w@ @'5QG.=@[{AlH5>_.]J OZdq}@cTo5ňz֭4Aldڨ+rb7k,PG=(-;zwUkBy$D* v kbͨ-0p"X{qZ jFiKѤa׭`/AR)@'0hm I$b%9@ D6@h~`BAH 0?@ecA+¤`f 0 hw KuZ$9j~SʥvH߽\ECyo&y3ʀc + &%WqVS@;o~#4kV>x?ڢF߆jqޢ7ڏ5 ~(=cm4$uj+ 3]Roqh^5IV${ Ż y([_g&MJ0X?4nf,<4|6̑'>Xߠh.Ea *c+bՐ[~Zr 3<5tq=A9]BmW*C,Uk1x5 U*js@W*h& W+$5r]E\?S']eN$<{Y020{OdX:99gxW,X v֞.SNڎlr6LT5 ~:#SbũڳL'Xz oݪLy&IQtSU"~t`RȩT;TurjRO˿O⓳kֽFy5TMr\0@V,n+d*Ik|o2>wMM):1^~hc($כgv-CH=x'ʽoX+xǧ8yeH]SY~)^ɬnn@k5*f+MiҘRn[sU'5R"L4TF P* [ ڤK\n \W*D5`oQP'M._@ TW~k7S yYOs*CՕuRhɨֆqܽzg'-140 MbIA3POxpH:IeKUjCE#,Olϵ7.(#i1m 'ތEP7q6="[A&OxvIZ ,=h ^@Gځxpl" ~q@`VHp+b?t20s47ad< Fa\`隤6=v[>1VT.`"1[W&a- "A;f3+2]>*6<%f$@BA81N*jv"7#V+VWȭ5*UHmȬVb3#i0tls41;GާٲYII/MM鸸/nfٲۓJb54d%^Yb˵=4Yzo)j}Qf$sYI/G7.$W;ڽAw׏.܆}׺Ekjt޼'Cd kmZGZԴ4V'^~JazWqcp=*,1lIlTz3)5꽦S5ï =j k|KYK5}s*t\*՟jU0H, ^#Oo_Fn֥ {pY-Skq9S;VNU\[5ʺz&VȚkC^ Daɟ0\,}mAyX>#pY SpjqZךgV;6OiշēZkv~h @΁L2q> Ce 0BCZz03Ua(+Rr'Iۓ@Ŋ1‚[w^I톃@(Qց "$PFY>T v[>щLGsA N(H[F g(&OoiL:V6݀5 4`3[#4 -GRD@ٶ1J:,pA(έ 'lU K~ H#=ku&4lj{fD~JՓAfن*EL~( h2ymXF`h5,(0:T74Vk*zGuK;Ml98jHDbZwYZ``q9*g&Ȥ{ԃYXlX,?jA@  2jqi3*YGE[gkB#jԃH4qA$M x"hQ488~ A(&(7s@m"#(%$ I$ѕ5LQ,EAZfrʣA&ɭi4c4ߧ-MHrA2q@f(wVQfͽ*TзbcCO 楫<Me&f,+1Z ^h$Nٚ`w"B9 ' F>k1Pي)z݊ DdHOA1V dA.ъ2f0jyԪ3A AA.֦;vk ցw3 k`Z .ª3Z02FFwWXT]NZ*ɁҺDP9AA=+C[;Gz!eOht9;rܷ?cZȉC h-oN W5X L55ڥu 1r+^07YAֻּ@]Ey\ , W5ՅBzW]3_Oqå'{,+bk [⭖$P*&kZfb_͙M1;~$ɩ(şMsvVzmxǪk&եQ+Nч&}|@ MO*ylLx?Qw>H]my5?]g]l>cRQ7ֳ=*I]j;Q"k8|_P 2,2rzσk99-oWWR̜5?m_sd3|f'_o״=J}]{:wd{Vfƍ:~Ŕn6BL氐5I&JW|qYUo 1\W:\,miHįLEj{ԘN:kQrEN:JLHbL/=q^ȯ80f q+q>Ÿu^+=OgË40s?C)&O56>҆` b AQ(2:ԉ V"Fj䟵[ +#N.Lϵ0WAӥ lN P+{6@3@ŶD=Cd@Y,91ڪ"9)z1'=( pуH Pps@p# oVrhjQD\v"OP3:#Vab?YJŐì*ҷmrgl2L b8$AVA]z+zL9 q&h'EsSE2bST}1SUK6jե;A$ Tiz<~ I4 G+WAjܑF沰dn=-@U@@4A0*BI@9hUQ(JJɜ8sjKnhabMKzz'ڑA)Mc"D/p P8 vh3DqA-dE Dc?ށt*bEhv@j])EQ&dԄ2h++pH ƆVsT 4jXMZ$P}X`F*k5ǽlKhQ8a44 XM1[JA4 0z$>_QI4B AW=Bh"EqS}b&A"4/~n+`kGP`UG&L`Cf#Fkր7 ,?l@& ČB"SG5KpTxU` \x7ݫp͡L]^2]̈́ʬ' W7<{]gYZEK=&:C VNj54 ai74`ԋBALv[3L6|@j;sSv91ZpdDZU ہ{f%M̒aZV}AnջV$*[*&h<1͐]QzVh崱,;k{L"5:NzVP#z x*O=(,%'蚶ʼnX`7M.p~h ^ V錭]Iڮ3ڻ*"sW}^R2tlۉ9?z& |eM AB(]eG9ABxB42N{jΥ+4ƚv# $bN8E⭄A'jҚ(H4Ni˓5Mw*#h9h TwmPs ١aZ8**Js2xcKKl̓Ro'>&QҋI}|Q/?!^ +ug&::sf&}!#NmLΙLU*q]{WIYbr&&J#\#?r(zT`IJţn o(I020JV$u0m{/A_qOcInj= i o7 Y83{);p57 'ڧٸp@?7ϻ>b@=b ]$'I#\mY&k($FB-+?z ^+sfǃ^\Xz%s|G5Z0MIY1[ j* j_g=bVxX% S|bɚ|($Ř;Q4$\8;TEǙ:ƘpW_QD3ecT5ï-Z\:US?kFZw0z^{:r}?b&9Tsl^YPԵl<_{UTu rg8?sb߷k'q9'5^8Ԫ7"K\E:/'zԫ6(֮67 QԘ8O@9X&?4ZZ@$PL1P,Yh OF i3& q5L{PLI5VL0q-FsXA :ԉyXCR^3ެY9u($SDH3H'8Xh ↊.1H?" Z, =(ŋ){ &!TLFhZ+ T+k{V: } !1YHHU ^f@ XBG9%+z!}D&h ڦk`[/hv ؛e8>!NfF^C߸1h6GI5gjg so㡮ÍF{P018CGZz ڲM_0ɫ,ATz_ʥk8]Cg5~w:79URa]״Ni<2uAvbMo~Qxڏ@$VI6{}Iy|SH?Ǫ>[b?/ȾҮUZ䲟H?r98dn$03??嬘t^?x35t+i;~u7'yo?NK!޾Hu]?=A-pMdz5Yװ1ͫYk sD8;Sq۝mEs;siIQ< xDoD޹cꊺbW_aBMpMr4j4"G/,TD@_wU:hNA'f6:T顨,I*2I@d"j]sSDt(d@A53NF [h8h,c UvہX. v!۱>OfVgЍ\jL't?z05 bmF横rL]egk< ɪEծz ]KTzUr|@jTTxPA}Ak&3z sW`?zG:H&Eu5ZG*a=\)^cfc'WL{?"xٕ`{W>OH~?˛3բ dji`aށr'eU@_ZDH+Ƞqq@B hOJ@}EA"s 2Im#|gSsLM"JM];OPRA,ebp1Ƞt;Ko'$Q+Zsfjً109In<~hjU]ԅJ_,@[TF{V%e(ҍUҠASpMHtv="4ZyG\:Ɇ=`gs&jD7Ij &+3DSb#E e62hn,*ڤX< *'ޤDP,-j!ouȈ?5l9BFD|Q (B ѥ-OMnP=T$pW Z:@UTX"ɠ@PN%sA6"II"3gڂk h`AYXb1A!",FzѨb,H N?8 PAѐI"1-ޘA-@EP˼~./8(be3'"2lp(܂?? 9pSiGޢYԷ-+Lnf>I.{y` =zW;]x޳WXrщiLWsI,YWջ:eQShp IFsx\&mKrn*G׿CxM@UH!A۽f>KHm-SJ#zjoIȦvfbђyҢ+Wy\gSLI>TRb× 1W*q2 p}2kuf)MUwp6zU-ާZ*, q jm^,[-FYH #41~EN]}tk-n7Ia7 \V&NEF?ֹB<;W!5z'M 1QU ߽Taq&4X2k6vķ@7Lw5PR ?:n"Xj1$5tb['5tA&Nko;"kp&I$fznɮ~s"ob:UxEc:G7.iXYvΓa^^+WٜWI\*| ^Uoj3W*/*Zan&E;9Njk.bd~kycǬ0`_ osaMbZ:kR4}4đ_w J_}s+oOuIگ9WO.mw1w/\Gv?sji`Hןw pMy/=3_^Xמ~?'(`_QXK QyS50kaU*oVOViLTY57$Ql~dKdSAX!}IA3SAPG?Zmݚ ==n چ1jM3"Ҷ0 /S5)%LD.<3<5' *%Cƪ h#Z1[*Ͷ a&0@I2Zo$f[xLU;V &[UOvIڂŅ7MCJ_ޱxeDqYZ鴖s\lfq޹1nZ?`gM$VX# Sֳ@@& HŦ 0-@#ŕ+=~h$A4fXF%' nF`a4Qcڌ)FPfE94 tC[5>РZ@Ҷ"zT[y Eaj"\U+*J` Ǐ(|fT%Obn4P@2NAcH="HqAI@& hq##PֆVƆ8<:h۷+@Xm3@f-2"s@P:.h$@ Q2F(Eg4agoZ;(E&+C'4A0AP~h"94 2H0@"Q m@IRj g_>PKf&hh"xx hKĨ969Յf,j*@ʰP=W*3|q\Or3\GPk`s :qAq!r# g5R&G-tK |Y'nHEtuA֕:n!Dt4bOZRޛqң*`aM֧=띊iٸ 3Xh:Gn~*m8NޔSVhK(9$IR"W%wE(ߚaű/:hh#9v-(kάgy?yA}V~)ԬjR cunަ\55[z'Yh 0sltc@RX*u^T'\EfA&c̡Tհ;M$Q8vy U1B3}AMܰ$1ʪeɘ$v(2r8e `کy{V6#MD Ҍ(sXauM{zSAoXH늛Ec oc&Hicϟ*bQSc#FjVP]زjן3j`_+&697?QԚv9Օ3ӵH * 3 ɓҍ5B$7 \^Z7PL.h`6HS3@'_=&`*rfP>M,x+A1^>0x@*Bۖ" Pi #P8h ׂ, ѕu<ɡ YsBC 4Zf*x 9言&?\I㸢Qki2zTݽqZ@[*ǖH'bvQkKhb7r41R*;Q*&b-X`ŵABIR,ٸck4ŲO<POrHtns&zYs5G2>+88; $MQZ= 5 &(سeGZe9D,T)eqڲaTⱃ!ڽIoj3D$+z5&6 F 6!qA=oz2M \ɠ(z ԆLqZ"=KӚ%#h>`sAT 2k0"؊`p$Alֆ`AD $@ PK`@K۲h.I(#@T|҉&Y5 M=3SSL3R/*h"jE (Ƞ` PH,6A&qրd2h*kC+D& =A OZ04P'A w H ц`7P#4 SUB;aE+5T YcAzGPZ"WpY"hh3EaZ(⾡Ek\xG׾'/X>yWhw+h6$:Ey~&9/@ fHV}v vEV*"M\V-9]$svW"-Hnz!q RuXvah)`G5"+ EPkH9m@}SIP0$1\aŒǽMhZhtTf9uHc׬PWytǵTN⋶c'ށ^pz~fW{?sUTpz`A6&Os֥jv`Y[quPL3_أj5j3)-Tj-Jb{֥BPNj F tB K~z) T3 sD*kYVtr. JNVBc?Sl`T([:LtM;dX?&թ6ttOc]=4-h Mș!7 O:w?Zꣽ>±Qxѭʹy ǼS lju { ⥘ߢGɴjB$=+f NV<[adz rDh@[`RuR$ UVnh%bUKףBcT%"q]efvb(`<I1fԲ1jff*uBhZIA"kE ܸߍzMG:ϙ֙uf&y*w2(mzqw˷_v_%zPEi7 55 ( U(^TDږc@UCg4a;h2b I0j"Ac[,rMGOoo.mȐh?Hށ퓏A-d4sڂFv~l1Z$XlF@Вӵ (b ,G=ѨhESEEn%mʬgH+[FGVj`@o1`sAؙ8}-"g;JYE>XXO lʊcVьF+1'Q3XNd ևrp`" ⲴeI`=MlY ڱvxnڒ9hɊXID9hhѩ3҆E* хA P4K{P(e1H" "\AY 8-sAɠf Ƞ{bfglfœTG4"=("ĜL, O"@@ i[K'5#COnDԵ&4Z 2z1PNmf0FCQ+Mx%hFM6F"jEZduI#4 "=(DᤑFTJ5Ñ"m$CI9[BVh&@+5Tchpahq',6i<@Ag?4@Ba(3T5}Ady**WjnZZQ8'k:_۽=GeyA OZHeD&HOkl#jAc눵N?8t-FʬLb+D2u ucBIfxэ-bIɬn-XϽ}Tkp4n @ sҹ+ۀd7xqY$* &{T5>FiO . FB`ꘈ=j6sP A23D}\>SYc"gp3@ڀmďzb?H*]{ t}OT|Q._6sOpOo5'Nbݶ z]L?~t6[%ނxc [vцhѹ Ĵ4Yhi'j7Poh>}܆rz kxnI,[I+T\jMsa+4f&b$tU1j+.5 M.ZbPLAޤ+S'SZ1"+o?Mj [p (?5l_z[5#>ZGr57|Ȯ{#tsW)đ{\*+w9ǽT#NSmF?~g}~|Ơ+ȑD"`GlA[RO4Iɠbp` UV$WED@0G4b`lN9ד@K޶dr:֦}%"4$@m.n&`Vkl+gy55]U=VR@Q"Mx [ zL[*rQɣq7;cVp\-eӉ3[Ď0{nDObG{ bOz Afh/w>怌ŸPYKᖉEF m=^j$ A`[ 4 [T-cua6Ǝ*kbݱ5Z2@m犐@7j n*`Q)9``M \Q=&{ށLP9R})4PIT3Ak(E#4V(&(c 8 A03Ҭ R(qs@7ys @ '$(9mP2YKTy[#CN+*KG5#ATWX5"ˊ hc5P8Zж64sj⁊PF'AAd0FqsA3ށI)l&sLb-i*f TeB@K3Pʼng]l~@;}YnhqÉ怟Sz4F8&9ozOM\xmo j1qCk3Y" 9|Ml<PBcjZ{@1= k/Pŕz'QP&ZۻuyUOq[c/2BwXLkߠEEL1`2d3UᮛQ`/LOXsyh۹i*2z?QU4VڍA7[ 2Sr[xXO#t.FO%J߾۰\oVnw="&9G{۶4NB}lzimFsWP@'MS<#TM]6;f~XRxP5$dG`gB0ii1mV F [ eT҉ Lph)\&<2ؕWy1۽\`Nw^\ D]bI@tMpakuMl6 wHbי\T+I"u]diYzT-s\oNzSMtf WiL EuH#=릫 Ԡ`cq}ܜqcV3n+@UzXWnZ`"ޫYb{" i&bʫ޾BϽo*`Gjdb ѓQzJ,D@e&t2A kK3b[Vm֮!n i_@x;vn9XX.ńi5t^`>sOVu}U4=SwٗE⯑W:ME&;I}GDN:V97U<,tWSZOcPkK3Tj :-=#Z OJ{>߃>ڍK9|}{^"&py1`%d9+Qk{CDzcha7L`Nd<6$ȭKHeQ f`=$L3AV!`Dց\&A4 ;23A f{u8.ց5C< Rz֤0A`QB,:щ\ClfL5 y#8pER4b'/Dh9sִ8}MV,$sT@[%V5IQ5wD֤D@Ͻb?` KzL4Vz)v6'HC޲WXkg bxe QimD 'PW.Rɓv@$y,怫g[qdXP<ś#6DTnB nk(**[1$E( v>FRU,L10TJFh&IXPDa>(&F蠑(gLbh'+-DCDT@lp{P !"OLHOBh"FMPA\ހpKOJ捇0xR[fA~1@ИIJoYU"M>jRӦ`;8l@hY{G W4 E4 ϵm3@3ڪ#@s@?.2s@!h@dQ&`YsE!0(D1{Q?52fh$r(JV+c6cVP@3%[m j((cFW-kֶLcQ$jlشdLv4ƾL4}A;تI'45 탈A9[n*,zm1&|P hd6v q1Z12G`zf|_$}lII4kޭvD|Z OlHd fk1dQYtx\3FŽSVoYAPvV 'ڦf$Q=Dw ChV({7HMUr$F*_2٭ WOjP7`sVʯu H>]cI Mm& ޮ'k`@MZvA=j5/mn$v4#Fѷn9` W*ӁweD}W<&m w޷DXV$vԩ]\uU6hM$P9ZŤj9ʵb-ڎfVTTvՑiF*N&Jc>lS]%f3̑v-0J3fu"LV5F VU Vf[W0-$5a#k W1Vsڷ*^mzg}0MWW/0wv+@ݺ hk }5ʕmLZTtnͨY9UcdWVmA Μh3:r{W1N(\P/&bĖ{ 90{}=*Ӊ;3qگݘ-{*0bs~輧n3]'Nwa9Bx+LϵW}7OK`5:: >9,dm{~A)Uތ5 bNij7GfXp a5T MĘҫST^/T&FOᕏq";0+k䯔vpf;9ÿ Z7H}{^}:@Wțcx=UhЕKm0aj~G,Eb@u~PӰϾMm}"czRkxo! Yu n _[hmc\v4*6H b= nT02`E5ְWqA@dF*ˁեJbMlyVrLuVo8Q[Af$&FqDpk-DFjt2gڨ4LnԩvnzW]>\;6HѳdڸZ"ݸf\pR T4Fc5H贉BAA$"hy& ZORTUDQ3 M bZ0j+cv"xj܂"kz{DTT'&]Nߟȁh<Ea6sUS3ZWXf3]vR5SZ۳֫DMѶ*CE5Xg MobXV{4"޳ݸ}&EGh&v5W$jەl :q'9t88UzFzΦIaB;;YOV:}JN⦋hAt`ssb[25%yS[-Iqh=k}ɉ&٘?~#|ɫ0^"A~3_Pyz=AvoW/#5y8 2=zY޻qU^~t_T7WռZkH4zi[`i+da)iʃ+,f ]3+`2A4f"ⲘD@R[HXA]e.8bNVI޴#|bLfNduwoH?cA4r3[heLd{P($A=.1@&fI4 ]I4 n"&+h:QWqԏNcT7G+0"ęg [vųj*AeoleDG 5 LT"THvӒh.Z`G4MC3JgDTtc ilTj1'?+zјԤ(Y`28R`PtXiŬ4YryX*K>¨AԵ`&Đ|QFT&];G$E&HremH+'tǽB3@w= m@3;&D pD6"33A 'ڐ 60GCIl*AVP"8V%hbΝwTִv ? jTXEԔh+J6ߵ$P((`&fLLP&$ 11 ͱ0h YdPB62&C#Uaf(Z(&iV Znf`S^EXtM8Q*>kc+lpk c4Kk+l57ŵͶ*G}[m]sS*&~OsZMWcɜcڷ[,C2Ng5Zmil Ł#kq(TZc3]=*4%SݿqښsZuӼԱJɝOzFƓ=C,y) a[HkX[-*ߧ)/?zƦV`2$lIbA,Il " D56 Ȧ+N>DGPF4Ak0yd?9՘Ė~Gnc|>A3jlntsRlwjbji{TXYaY C#ް >np"}PMIl t҅p5+U**ePQ6d0h[MW+0gUiN%cp'y`{co/ZʯyAMu{U\E`ޫ59bBU,sQTn̞jk]Msilbc1RA3S"U Hf j5,`teL% +KL& ں7RUbF Rk13Z|Hȭ-?5:C82*-ZսZTMwpPZvN{I^zuT5WϸI\jg^xAW;YOE,!ff,/9H6F?TU*sjݭ tŃmwAӧ; 1]'HFBdI\@۾ ^c莕Z=U$N#4CF?4nqU:a֙93k]'F#faP3^'!]xpIʻ4yzE{kk6-kx-p"ڕ19-о*nȩ]Q~kqҌY~4SCeAѷҁRLU@ ևy 10iBu@;b+N;t'`;sT^u,z.щG*@z|6h 9(IP ܌@ʁނcL6yhpp;UN74a# c!hzӣ9ɪH։cFUb˶jpPd ڳdNf6̃2:hn"$h,X zw0"ul`AT)le(#{`?5l XMu3C֬[k+⁶fdP  B$t怄mAd//d`B;@n*T;\ۂ1[\zD j*u,16#(U-ңHbM@(4 VȠrc@dEqECL@q8 -Ah`(wL'GL8f7H=öC nW&I[dV 4os{V+ [H*r$F{i<3MN%haLB9>( CTQl3*HYe7h_.$@35, $㠦  - YqÅh+ ůZh=ڢV\PΫDBIM[ %f** ,==ڷASpYIU'=*Yd,z7Y.\!Kdnh}YfĦsov|89Z]ވN%bWHlbjnMhs# H19T[`q\li@k =0V&QTyL魑uK ^;~by7n1҉V꒩r85`Wn*UMӒ*h~f㚸OںD ]$e0$F@3E0knMt$\mtbH(H+epgZcbI}c& cydfڵ 5LaPs`eգMl>G^*r8x1SS aL_Đ&p& *@fL,tsv-~Ω$IqQW Dڥq P蚚sXv  VŪjFI]`ݫb@b{-ea- O! =Fjd |ʝd_ޚb Oc[Z[sa0NU/HjVt8 ÂZW4-M62 l;wȚ+URăz+gy~\fp*.Sji[*0>,DRchj[2(.[7@W  V+Bݢ@M]ڲjs!`\5W+{F+ ]B!jP!;^ASښaq[&[D[Āi:fH:0A\{{=0sYznrr^*]=k9pv­T@\k/@ Wvz2k5HyqɬÐ@1kZ7 1[QM<$Wx4S㊤gl`:-fK'kQT[dA+=md" V,'\H`ĭo]I3%zbܙĞn3tڹ5R+뵎  UkqA~hbfߘ 4n oLp* 6dD"c5Z`Vs!M oT]ǵfh2@DH[]7 *+7mQ'nU8xV ֚ALi9đ[3Xڤ@'u8֫LCˏNC5K+ h,X.911nA4Ĕ,Z\msF'lŶ$HRʅ2ev7658\*EO~H'.4j\`gEs,[e{V~c ц8&FP`9dFՀPYl$p Vx!TuU=N+) pN*zÞ- PApb@5"MعqQE{@TaEtXm@+W|+ VZjHiA]#KG`zz[+u=x>W6Dt$b-$V5^5WkANIn!F9"Utz$EV&;g<ְ+V2AJ |UɚWHDjs]MlhΩv31QU#Nψ#bHѳ"95ѧc'ƺAWЌ4ǽr\BDةh =sF>h58wT1܊`'U$KHD{eE i ~CR1 ;ʝzBO P@d-V. sWJtwRO s a7*natTчx'?޳hc\Tl~[Y:Ui TbKK/ӵKp ԺFbRz*.F+1HϫbѸjJHƊtE=ŏz0/>`U!c4p `Ԃ1j5AvղHj=|k+WO!wqY6~i+lmΟtӚʅ[D]esO#ڭWMftzi14` Ggqa,A>-%OlO)skb7aV)9&BVIV`DMrp ߊTr lp8^Aj43tu;-91h s##޲I汸>$j50,k(x\LĘkssRo&@ cz{֍QpLyNjDFz{U@Nj[Cgp{Љ-ݣ9'VԼ\Eef_0:֐8S F|ӣr `-rI* v!uLz)gނŬ JA`q3ަ &^2ͱd7T#ylWhT ш1]ǘ 4f4T`N4,  (-!ޥkr Mj/ZYj[vԎp*Y4nGR FZ!(8Z1"qzl@ %F:V )@VaL9}@P+(ZB ɦDX){6"^Er JXQdMUb<ԶDARe8SPq@{ Z҈pMNMEo}H)zA=KaofT £ P*DDh D< e42E":F zDd@i,ؚ2TTN:~h:6ݾV2b@3P:&I$z xD=Y* 4!)7S&LHLHd5 k^6G_KVvPxP9T)Afcz+@9v'ޭ锰 $m0t 汸)'d\v4&WqNzMtVZ 4!$b QӯZ0GI4`t}\ kt[%$Hzi\Ѐ:LF֋lQ .1`O8ɪ➫Cڴ;AJJ$Uiys5-Pg^ qMn-e1vVo@Ky}&LU0tHZڞ'P.㊚%늛*ΖTU 3cZV.JsPmj"iwRx"`|ݵ{VNŰG\eeIvzҳjUA ?/7muu7hE$t~ O ?jVƯیU32<2Mte55PɚƆwyu76j:}R r0~xԊ*pTڡ-t';4A'ʼn\25.`A A\Z Z!$k%ͫp$5u@18l-z,c0qU`A W/B孛6X@*.Z۶… yEOî]>_ؼёnhUz3Anաu!;AV$zFZ?K7d qOV?sq.-$>'f1-陆R#gzѕ,/u^0IWu g搣?޷:ƨ]v z!(z}[OfiGdtU]-zOP;ɬ6_ÿa##k^7I[WY<%J~gҺΝ[# RjosIU֠I.qkEI5]RQxw QcW(SJY0 حdkT[\ihq>3\mNPq^/2۟ls-Uy}^m=7Pa"_jhWkWUdj\߈}`ʄ/cY<7OrwBbLgAz7$`~R'[6psՄQp`?֩+Kkd\abA-v Bl_ITb"YZWj Ȭ OJ:* Zؔ$WNj 95T(T[nkN$VsVCw1CN EfE=ZX0Q]& \ΌQүLcfU#6٭$֣W=Skd@l֡qjL^LHZYVpZu $i P KDk@`ln9W=c|P6#31<0&k(OP[倉qkwyd?$5C{ʯV0OM|!q**ev5*TTH kp+Zc{0D ֵu$\ڀ{v݉#ʚT $l []T[TsA0` P8XMR۶A**,nR{֤Kj @`X`l֬ SONm)ؓ Mo*3[3=@OLGN#P#ڂVn[djZgb^P #=+*Ԛ+C5iC"b4YfG:*jNWyg']MN:`nI~'Q]cIqTѯԪkQUy?cXK58)_UP}@n!B# 4U-G(BwZVNba3Lbi!SCj^_/A[?T L IJTCqy?^%?V6dXȪg꾶W̘$)z`6}jn).`q*_ƞ܁c |+db뛖 ;I'xOVFK_D2 Jim^@ 1#1Fe5`pdGqI7uWc'p;ĶK>Hfc4LS H9W+6a˛k/*)_wdS*F?ZQnۖ">7p.u۶AOo[-Uڛvqc[Lz o1P}\!#Ae5@]KgɭGqq, }j&@jx㪐oI1?zM`1$f~5^}@ޕT)'q+~^˻$1Uzx ;A(df>)G_sl;zCt}'=rzA:Jߌ $2s𗶥_BT"A&Ly[G<#!nåsH4&jqES~(=)j_Rɲ195bڹ{A@/>[b嫗2N:[*nۗQj5|`qTT:q 6j\0&=^hm?V=r'hZ55a=\bϦʱV 傌Hh; ?cUSGMc;^³ tNa|-5LtjQH-ܟ޶Qw5;j䌚 -M=Q5f*jŒBkYVO5%WUp6*72 RkRf[S-Mn "Zn3Qh鬘1Qh Vh+̊K+WkYW1޵j?z n5pAXg'#V7sf±P;1$Qw u'4ϊUޱ$5R۴P T?>m.bǡP1Fn!ޤF2uP Ag'9{\ګd +SjVo*˒=:K]fǟV%Q@zJ wpAu/nWYT?W."qf$a?So:NGzP`Oʼng_| P["|S7ͷR[j72p׆}@6-I:EwB>Tɜ}[;ċbQp< ]cKKDD3,liP墌ƮKlA7D{ѵ|У5Vբn գcd`a', z^v~=zsTzN!Ȋ5z0 ]JQ>5*zq/8wB覧w &ȣNF(i+?~b'ȓH*+Jƴ3jשnj 573UY05M/ luqj֟T?XqbnP3Sz2ox o%Sz~h>TM_Il2 ]I*tu="Zw,y*-G0= #;Us!K}=u%S{51v[;`OT#]ۺ{._[?e~xajX.,\1޶F2u_įu ӭV Gך-u,KnrIUڟ5%R/lGA>]ׄSrci*q+.A"f =-fxo"DnI]:ǵX*ǁ۽,]dw[*l.nL'5x)gkQ)A }Cm{&D[{YHp~+[ʤC?koB?:p^tQO{W.|wۧ=^f_HQ=q_x/]}ufp+ÏTzgxܶ3f/V^0-&3jqN+OviixV23VR#zp޾YK(?jD?޼qVϝXԹ{I扨, 5T4ZhgLP5bK֬I|=&O=b6,!V04ԛLǚ%cP kP $ LETQqnh5#O`},̑A?υvIn{P:y\=j$b֮X b5fdqD[p+1 YebE^kq=LijT$pWH31ֵ%d5fnh"մ4֎#*j TZVY#5$" MPq9[+a'UM5Q@ƪ&Ájdh]K[G= zRCwXR^#$`ԩ 0zDT-ߎ8.Lc>ՒǜվF^z$yԟV.q+n\T6O?j1a72kq'JA{\c'ĠJ젌&è`B/eZu8;1A"R3<|npۧ1jc i)ciXo@2O/=+ק4K ̃Z1Ir ~cP}Wincz7}JW85Mo)*@⩭k: ܞP4t ̌Esf( q*1b.Z  Xd洜~*0F֞fAH/…Sϵe79`& {lI@T'x=V`n6Z{Ap dzU 5*vh3s[ϽElX88GՆl(oMDF왨Q=,& B-VUEK,*kZZu Ң)*[SՄRH%h,X@d*`C"L>…J``P?AU` &Mql5fu!ҁvG8t nEbM z0zxNڵ@hXl H f-LF-Af5m`\OާFnąMts\9Tj}ASir1QǚxK88C\E]Y A:k5X_w}r~A:Z)5MGh7u*=*{MN7ѷ7fڹWvYø y\wz <`L H5X𿨾zf}L@GԺ9]Fù0qFU}LVhW- >(/(lA@ tDNL,8z`-.9ZrÞ:V bZYP\I_PZ^g 4RVH @[v̓'A/.?h7mȀ|`n%bLE0EPq c3X(35PMiZ $hC1=M5'ޚ\M@v]G xU;}^I=GĒ˫C[DiA }$j k3Q{8xESjz~5:Ci湮5bjU{BF{b5ww,wn,vbts^#{kHbO}-M$jʨUCA3nDoR>[>LITbx,A96,J=:; Q+|xB34#Ӂ(S&HSt ?ڕYgk ʸ!g$c Q[vGKzi5sYl[#&.EMw-F=[](`l~Xc Q &k2 I$I<k3S֤Z:'Ҥ?o5>T-qUS`?k}EMW>)f,f2oL{/dT 5f.Mn$ DEӓ'#]N oˮuR{hՇ 1U kcҘ$F Э\Ig\5nwYrs1d5 mϿZkpژu֘=P߃bt4 ޘi} ulaZԁ%L5b %cYk\eOZvEcV`I+jvXr.QX7=$c5mNnio눜4GZ7l(*NZXoP`ց޼I&e uldUY2st]mW[srR9 bZt+e_GTPd?=p]'PSmX ^O:x׺ ޹eVy1uǴx?ֻP>?ϗZ߫<[?x,ǫOn}Dy֟WIDLdf.׈}GYsrm=jJ JZZ54mSf .肨&In4@EY1TfjA%c1XVTF޼o&>9W|c< >z;ߧ'iHY6و>ݽJ2=CuJ5q wL 1T]deGqX)$۽M^,AWk@*+WQH0,I-En|$U1 Ue3ǵ^. 1@j +pdwDpi؍LJ1{ &lSަF7xӁrrO8d7壨"1"ӱA zAԑ]7u .UW?njֹpd&Z2}@ t: iބm=;V%q#!$2 G^fu[`ډ7I޵]Cc0=r=Eh,Nݰ3$j 'lآM:(gLa_s LpI/jlax kw2nw=+1>Ut+1*YEL:ˮH$⢺HRMcq~{d hF zSt9 kXaHke#hLhOCހHx"(wvK,lՌҹzv)Mj5Z,?1+-),x4\`ڂ~>KI-#@{OnM{?4k{@?($X G'YS@q!zښΚϴEl'MssU=cJ5: @i:V7=^«D@7En5Z'?h4ԫҲ Vk1 H΂"YZZجQ[6\9Ef7Tw[Hվk1 i'21UhC, ҀZmOC[cI'Zw]l]U>@.X\vc4E7pr` V2l(nS&O=R}[l07tdM/?5mڦgm{Q? `{ %}ٟg6 Z3'`50$d{ւ-H>66ޔRQXԱmP<X[A`H >j@UkU *k:A` juN#4n橈*b#z-ޮ2sPwj7/p]#!DsjQep@`}x,2DЌd@Tnni{{0A=+d˵xG\R Kʥ^fS| 㣻]m*l~{/J>Aqlix-ⷼR{P0=[mcXk?px2Oa`zY߸ӸO"ĴZ၈[aL+-lI3U:&3q8բ8"7Wv2uvF:j,Ec D7= GN+F;A E+Nbz sI ۵/pne(Ty_Ռ; ԧQ-a [Rp*XJ$A["Kbds/6I?WhF [n!zϵn%|Iv2yHkä"пU9:lHKzTf0V_O}VoğEn UmJ(I |`c9Uh|)d|u}YjOWI..$MjCN56ۚB}EyS:"dצZ]*3T=k6ݸA⦪꿫!ݳb@K<[ƟlNh#9`FqU6iRV: o15'>u MTE]2@?novʖ;{haO4l\S1U]n& ppg5Y hjГ&8 e# Jf݄+@,#yVz[5cGJRźGn x [/~G(Du\zoxC&ۅ AuE!nPDGqh+8?aZRK`{0}'=pOhq' *[O2MR*x5h4 mH' z}Al Ԏ:MH7@R;2bz+ll]c5J`Y<@te"Nb$P:?Xa ޲.%TWHгnjkZ6 :T kP/H4n" D(QLfPIy?ڀd #@z(4efP(KRGځPEY@mS3A,@j%qGGJ`[3 (D" 9f]P L (+`Mj)!05+;5NGžur'P# +MmcaFǜԍz`9P\ޫ^2g95k[!s+q4YHpݩ4=:0ĕL(zNE0XL4?} ̓ }ln>7mO"Ef%dx4zu=ia"9Y o!n oXwI'w]~p@S20;fs\I?f1='U,smرcڛiJc횜n/J%ýj^6]#<'zo?Ŀ=- [y |'Qq[xg-=SZ t9j$Ĥ"y@Jְ̽hT5R 6,K?ڷ&x L{j 4?Y k_^=䫍iӘ~<'wڸ9| C&;*ߙO}E A8jI$|SU"UU 5ı4CK`L ` [@LeBVtKTVJ'kp $`0`~hy%hvhnXgs#"BbF~TvP$&[v yf.\ق9jW,0.""?4*Me݂'$|V3L@YS NQ4Y: bTs#T+훆6 %-Gb@."' )j>Y]r$ s =Բh~Ռ"0+л71I}BGz{ܷt5 }n0&zUPx#)RU"m { E-DaNE>_&P\0&?Z{4'7\LUJU.umbE\MCQ%qf+w;\J΃cR\&I'TJ֐nzk PZxۓwu0X"83QwzyƆZmĒ{yJ͌ֈۼ3$9NjA\zGcL73o,[q GuYq5\w?a!VqLcV<Ҷ2<5[Q|P LohuG64M=+kX2:ڨO54#$mҋnI҉N㹎#ޭؠH'щ3 V`ceP7v"ON.#_zPV,(J;8$=?mŢv,kG|V6w@Vj~廨L(":}z'R &cucPf~MR֯ $z3<{&2DAlKݸ1eLjE4z'ѿ]XVm*'M}<*{Qw I2~+c~֩8>ҌzӟP- 5 Am&2*ҘpJA<53p)bxf"MjNڐ#5XT hTxMak5$ȫ3Lc4,LUd׊!%rOA#t d4K=(A+؄+׽n1[zF}_ڵnVLt45t;c4hQB"EMZKlDM`~ 9 hܳ+P;M` Sf * 4MJ@"2+dNAց9ܲOs@;}UԖI>íh;*niHU nӴaX {jjZk;YŻZ4F;挭=Ð5inRPf>kCWG}X, dbmm57Nt%Zvf񙬲_dk|oNKpc>j#FI"G^gii[یl:](.:h\TqiV,GکXر)kѭ! MJֈ4#XІDjhC{usx0MOsIefLnc MFfhYb~{WHʫ$3'ZX세H\"ω'z UcS`HmwL!$rYMʣ$O&5xUu)pe;r=gvc(c_ƍ6u }gO!kl-Qpqګ>λ¿ \Vvbl񞕾E_HscfCVnHKOP7.tds[tV% h| sjJ, mPkR\HkE-M)rOJ\w4IQTzH@">rdVE34-&zA:}"+Gzb.ZZC#  P M'zU% m"[R-zV6Ц("uL"Ql&҄5I憓CQdQG`"8_ 6 {@⍁gxbƉ:(VjNJxi`1sR8[Vt9Ge@d]L U#> ׮YG-kĬ o&_](@$n9ʱ {:A$O^z}03>(Ne{qpxQ#9U3M*d,Ua|< 8{?k`ތf`ȭoLpp đL`*Q+y?1[ Lc`gRVDL( {}mjpԖpIV0c bqֳr&$jqP}u"d̙oq9:W?Ïo.ݵ`*d߭S诮Uw!: -hEV{Ç/?hVhDZcY;o?$fdj-nW=TC;]Wakt=k1x/.%}MO(OP29z "n;*hbf{+izv=kZZrĘX4li=0:dig8Q4#gXy]cAB']c vٮ͞/Ŏ|URk'7'ڶ$[Z& ḅAǼ@ۙwI @sȭ;$F'u%M54RqcRz;VkzEkmnʱ%W2:ef`6ԅ=Mn+~$@V1qZ]ww4 jكh'#1h!$q5PH6gԉg$3DGJ o .n'm!LӚP u Mg3?f2 \<kC9Xf]P1 +TS " l"O [@d[ ۥtJIM+cIi $<Ϥs-*tkinіXӱX *q!NndJh3];X6VhojtwOJc_bHqW} ger"O {d8kj=IŴ@3&YR,/FV V.Y\sTbݽAiՓHSOC99\c"7f Lcsw,yW rGI[9r">, ?tT_ fGqU_4Ue1>6^`"k}SVV#>k17:Enׅ^ hCk5je#B{u'6f $]B\0A@jkwوYI$[!wKg#unGs|c'W5n pQU9fk!i8T-YQFde ̐OeP."_ O_ں-sQvfpW1p>Mt.2j.X'Dg3PcE(]Ǟh 9D+w=;Avk)™2+cQ%CA] GIXဎP#ȻЂeXzA#G9h&vLԅnph $dQQaPsF$E,}Z["D<<#’A2L5ǔxߋf*gf,G&+Rýݘ*ؤvwn3SK=RVA = VNEn H04jd)"i )PniD[VrH)اhsU /d֊T '+q:kzRA+ s|5r93Ҥ^k$}0VH̟j4d_-`f 4%v9jT„uc,m9V)3U }G5غ0U' ?ƧOh~Ʈ9ש7ղ ZmY?.#9rVjUmhS:fuW+T_#>HlJZ*lOQ|]%-[ ]O9w$'<uB.- LtvuvH u0Ij+ٝ%沆iFcQ|j9%`jHL-$r#7}OCkw)umgh'o<u>/[-$1~\}۔ f+Y OjˆLXhmp Xʷq{I.L]cAqlȒ;\;Ael$hN7't4$Oj %w6ĠIhu"A,sڀ$ E3d,k7F#5!07LP'Օ_@jY@V7SUAbXR%fs4e\]F qނ64b$@+Ep$3[DQآ@]5$ 3m!dfk!3Mm z*&43'[XV4F Dh[Gj)j|5By[qU!KhDȫ4 +h#޺ALxUd fF_׏SaQ#$c[ pvif p3yk#43 -_@pI1U&rWAWIW:GN Ϋ; BaG[&""@%ÜVUjՐI]2lޱZҰ 5PAiL( l9"?&@RdIO( fLSfAI5PJcA! FMCLZ%@V 9504HL f' A0>s5X ԭ"2o0iW>j$\tG- sh~ZVɍr>#nrJ =V?ﻆdֿ+<\sP˘ɪ4j-۶Yd0Զl&CLU©]ŏ1#kQ {S|"o(Yr2x)U640A1/^O⥋Ih6 qa#1ֺqScTjE'+#Skmk'8|~ɬonʄ]"<צxxq5+m9A&:\9V^/f)0~x㈵,_!o*c{ZRW4-؀g2>jRE}Kݿpa1cNMSg7y `wwR?բ/GMEb_?jcmgr\q睮}]ݭp/@LW}#H\wV#vS[7HzH`ikDs@m3*֬!-׭`D̠z*pD?$`,i'GQL5+. %LqY3Xo+?zV8ڳ Xv!FqA n ̙b˭@5ѕ X Q$5+s֖Ro+X8ʖ;j`g )w_f2 oR- ՍZ}^1ˠ 2Gѕc$FKA~2g1g$9L]\2jXMz=k(56m>*VcL `=C5$J`,{s ުT9lbdr;:\O^߲"3]%SоѶI `7J`橬}+q>S/2˻'$gAktOd-!DTUM2E:X֕GHGjWR E*wM 7GQH>+}H'9`_6 ĆQ!Frz$^ H "\0;i6":u7w.A%!m\}rGz2>lbHq'jZˀ`A׹!6fRlLK (Żn/8\k;:Q85,IXyhw=a I9=SI%؂h(_&1ެs gH2Oh#XN qTU n>:V&H9}&F2jԔ@ɩbp7zqĒ Q)OʑUTqKqY/7щ` &}P+ߧ"zjA dyѲ!p /@$#RŒvvV,!uja޵3iA-kRKhS}RҜK =L',LGJ/ؗd,2kbkIIXqƝoL%m3*~[_l}ih#t|:Ӏ!fWyi-"{5UOAV#ђqleQB02}v#6 '-mJjԦ-3jح ̐352eI\ed ҾۊEn: XY)<ޮ'mE(H@.ͱd1ӿWi+T *,fjmϿҺJc;TJKfzWMC \3HVT|$ԞiVOj3:ݦ[ .۹m3nGzs" 1. # TOI 1 k YBPJSA榍{ ZK3p cuf㲪W`}R`wAH&1kPxcV)mX jH挥(qB]+\sUkHT#ufOrU^|YGo27 f5/5_DOIYk=\zPp:U+3A;O: 9CUaI#Ԗީoff;p;7t$qҀE[2&MC'@C[]$U]"'S&-~jp [nK$0oJ؞Szv{k`0̀Dzdڨ@C$mYjk'Xуnpϵgݶ:w1ɭ{'2AlzG=ˠ4OWu6Y~+Y8E\dMn$ ?@7/ =ȠC:bDաl3+V'Vvlx]@#=<$[Vʨd⡺Եl@ԩan-0+Rҿ4 @Ko?-A54恅γAfy*4ߌPacD$[-#;P:o@A4 0GdbpkC([h4YmA E0?P)ٸ F(6)n MtbxRf#xI5λG}k,yqˑ=<{׮]7 p&^^#3@i7["F9Us5Pܒp{ITOzS+ =F  =xnsTu%d{Q L[~n[8rACJK?j`7nlV$ AlX /mX''S@0zkT{U~՘Cg)ʑ$Xԑ݀{U  4YC) {ՌR3N-wOyDsV<]ԧ~:UOc隷x_ }/}oUxmdki]gj>kg>rN~خ bA9S[AP:- *P>40m'16yarT Q8nǜO*}'֘ fIMlfux,&k\x5κH,9M`kO&[m|ޫ>ZgF7U9Jrt0(PD'KVXl[]A?VoPu\؀IN! 9]abt | z֚u ކq&+0өث$Vqt՘70i˚[I_jlGzVi~Ս;[kz62ʝøt壁Rh-l'I&KCz+I <c-I/H?5-20'ނgS[ڒٜ,ԇ#qyzΩmcW4o ȣZq3Jue[LӬVV0Fx&7 cn3-qth$NIlqe+LAB'~3ϵY$@ف jbhQ:#Ҭ-3Q}ʄ8봐MQނW-vV@:Aj쨲z2ZcԻV0aꞴԅx@a\zzEHV2qihZ,A}'(^ cZk$wFT{Pᵆc!=kuk[c |s8YRF o<4v%7T+֯`kP]KHb~fӻZl]7I#f֯5˻ZDJ MM 2N=KWKl 5Apb8 UDA lFnƵhBKGx<{}tW&Ɠk_"e~w%Aj(Ubbq1|R$OzS qB`Č]"4/=5sA~稑]Qzm#lnaL'MŇ+|:Ҍp: kNL\?5Ʊν;W:[ `Ld磨Ar5q\alt52epz[ߊ+N{]l+?Sy)ƺJvǰz2d"TcR:H@7ETn%9$I,d3*M{՗%D<^#xkk22x'Td=\sT[d wU@9*yZ A#?JN=V Iijt w⩄˂'IYbjSU I4I])2bOjzF& [T=jbaToN}-)x2Nk U(B/^\D,t(bйFZ d@ *D8ku"YZ4Ջ+ꎕ]P4mAQ5-rϽNԴEXV{AY$G" њMihY4`tDh&[1S@U;E#6= H 4e@(! `cpD|:PGZRn]H'Le/י}jg9bg"lN 榮9@+]񴴥kN+mOMͶ7H㗅M]U`jt~<_wϽ^xs{WX >9/!e+s@81ޮ mpGZU}^ YIFEn0;!`qYMWrf'0@sZ]r:QF$ u$4mm"(QVE\?& CCdDQ(ӈ2 (jFFi &I3YZj:&U) M&CޡO,:%Bd%a CkNx V5{E ZzH:xWz4 9DN{^tڍAgO__we|7YevgYgw^SQ~jFYu 5HugNsAꒆIZ, O[Ih~qJN08:`7lWsX Cˮz5~ -%5,]_nVH?ҾWuc5x2GzL n*5kN&OcZ[V샓r:bc8jeO80ҽ"a1ZOikq}~]&[vV7SC10[V,"Xq֘h%LֲR zcVkd[tõn1}Ap:R{rf l"58YxX5$'Va[׊#]R<沒1n&3"'oL omAjCY]Lt5-]7Hz"Hb>*kG:I ` Əc^ڕdDTb:OeLM`c N Zփ̌!3&mL WIm0:UA E8ю%Zݴl]eSnN+m^ME}w-]ZpëIsvҌ713?Ҁ Nöhhnh4Ţ g&z]rL7P8kM+3H;GSֺ!um ȫՀ&2zU鑀;bh+ski]wsp_ӥAUQ2q A_mmK`2%ϵܸj+mE,@8um%QMzn*ZMZPֶR.L^Eʶ{W.CRU`-{:%%OCsc FrDHޤti{sCH23[UueQ5yƱظ$j`6]%MVl~ֺJ1İh.,z*X$j*`i85Q"Sps1jzKz/c|ݤ+ 5JJ$fvX0:Q )%V'Ɗ]ۜE,-usP.0n~m?'f Q[m7~H?-4dM=/SlB̜WIS-cUan WYPMr nSjnZ0yA?599_]t?zd{*0T1ǨzU.\Q5Q8 3]rc1(81o ekRŖޭ amnDn{1& g<јU ƆsA%Xu FĨ9-a3va jwmַL4Tԃ\M$&"^WؑZ nғYhX!%@ڢJyx;FbUGyK&kTm$큏zek=jP%I$ 84m A=D@sAfFݶT5nķWњjݛdY`BxtKz7~ pVLxy)4%GöEfUH-sA0( TI$fWFfjf Ȫ sViD0A諓Z+L` Uދ]Fw~8?\Ŝ5 Of?+U`Ϩ~iw>XتTGԁ}qԁS`R&TIoԨst{:ˑ񏪓kKEsWN6y˧Jy|gxo4u۹h&8ay Uxd%Ϩ֪TW6z9E`" g]QBں5w5U o6HZP{n  ֤a|dE`dKTMEm zV,i1T6 sY]REHۀhq5gӻ ^aqrvO,sij1ZݲlOEN0Zdbxk4jD9/2!Oĵ*ii5If }ZhNbEt5BH5Q !Ȯ/{#SXڻBH%to`kѻtANfDvyDUT /5,&1dbVɶF]ʭ$M[Y Wu1ő*n֥pkZ漙Or(Rtœu;dO4EhIȎjШڒ l3 YTL}F(EmXM.y `y`ē*5gUbʂ==9c61;Ae3zH$y^cum;eJ Ә!p- W"@)Q 30?88fOL7NFa[BQHeLzm ֞.`r;i{zVv>{+(47n+k5c>Ib~+}Mq +V,+SaЈGbl[K-߾:ְm+DނkuI*wm84A(Oc@bg Ȱ Q,]G{Gz&Ghׂ^k,g2qU1D޲ %b1t/QGpLOO޺D6mF.$ҩ5=~h.0$|-5[fSh&^($s(];\{5zW)#q@QHֹUF t@Kkl/=#YTMJ[V9%M5@+B -2E5A[E^j榆4@lkeQMm/Xj5[QB۷갢Y{L}bLi*]ؓri)\h[?ګRʃ}zq1.4wg*xPߴVȸIOjU9GpOFin,!m[bFG بk~tϨA1\tԌ 5׈I,~c^//+mKwݟQ4|'ڡgl7-mJWeԧlN ecv=I̞pe V85@y nɒ i+m33+R8% lC#DZLQl]$\G]e1T&J;dhxU(H 5z)K- `PӸJ(i1sZ&4`# %n,2=lQ5XxCYS]He>ګqB7rA@\rc}pxIB'lqYHċ ĂÿSپ ZF ɘ84U5rڟ,x'Uc [̊C0{f8k;N*ʀKک)bx[- #"X'f.CD=56° h3nV5z+E aaZcMi1fq=ܵli35pz.e8Mtzj LsĚٷt vsHGBxb՛̒`Q5m\&>k+$::M}"zG :GiB\ZVζqX(@E7 HZܲy4B ? O[4 v(IB,鬒ԩЛSAbtO [J:[8hE*@#CVS]ŵA5wI;\ڇgul=X%X@'vQJD(߾a5qΩܹ#9wL oPCqDpꠓކho{q4b>nˀbf(lDdѺpH P$.@5";jQ[/ڠ"իX 4Rʍ˒jޞCPwIQ$Z AIhӖ9&jx~FWԇU(=u{wNfLck<2ot&;^w W dfPi!B+NjL"~kkώrn"9ןگ/;L7+="[4ɂOhԦ4@Ypi*^fL{kq_T&AU+0v6 Z-RF0/}1Z˄5hk1I&ZxPq9nAPtG95 XߧA)Ljni´'VcFlX 2f},&Du5-7O5 ɩ;gu8g`v- =4u8#n5 X̤{7nj@1fӞ:uv^d]sZI-ֺAkE~]w] &u-1Z4\!qn+_:?#RĝL@sSRp1XV-c Պ( N'PS7 h x(e$q -*APm5Q5ͮh&-5q: L;6tFi1H@ QPI,FڪPe4'l 2RƂ ϪbjqC";!6eYI,}5QeɀOs[5OJPۅˀb8Vީ-y'*ٍ-vjǫzkƦu]u}v@shH=y!ma` ~{'9vS+|.YM։l{{W9OoZ)eL`M sl360}Z 5H]!0XBmp'h sn&t4Ž?'J=Do:v7կgbȎ#5͸kEC2q15z&2'u PF0uh<}sk4%T]c;kf7OZZӕ6˜WHb ֡x(3Me f9bfkc셸=vU^2}-WIuE6ӵttyp" ÀHQzmHw!ހwo6x4n4=`vK5gLqY.mKW"xe˶,&dSвi(Yj\54>oSFiޢ9nY7` ^^qQ@`M=U/hl9601v"#گ\r~#W|N}20t>Cz=mآ1&\gZ ֱfͿ@ @Kv Gvy40u b 0>Mo3 m=?j<0{x\{Cq c1ks> +ꕉZW"A6qZ/m<D  ba4bv"KO@tӺc sӼ\Oq 1\R+ *kt6&j'"h%zN*=!Eju+}%AFԀcx4NJ}zzCv 0޵?ſ3j`iWH9-F[ՋXdں;3:h-z [騸[g[_ުk_ɫ+ۄWk Smտ]6nDf5_g\k>q'U%(j5yqco5Dqum5׀ nbI=Ȏճo CYڟn/vXU՗MA(?4;R_f WhWnsc[x"bzQfύyHr2cȿԒΗRm ڧVX5liW4$+OGtm?#BҾUʆ7LIV:u>"  t7}D"9qU943̙CUhWHNYCl{&oI[U tsVC5-ZՌIhwyM1 j,N qAlUPT%=}L8^0 3U{d[:Ua%h^ָ;UkXʰJi&(-idJi=i( sw(`/ 3HRME,x35#qH Hމ sVMA%H4l&n-0'ު1 RmEVH=MV`"@$v5L+I9`9Q`d` 7@1XR7}$ѢZ6#ŷHoUUÇ>{Ztٌ5ְ.6>zY^^L?ҿ{gIw{bUˮ^ ʜ+2,66.HW)v[`$*S6Ż*ve!G*HUb )ڳɌVq;`bKoji|)n33<8k>A &pcn%ԐWps티˘-^7tUuƦ@;՚Ư Ac?jV 4Ԋi:U띌Y\z+W4WlrFzt61}vLr+zu- '&d<(V-pu#֬ڴY@& BԚbŤ"s(bVl.c5j)F!'3[>CYXn/y,FvL(ێܻ8u#ډ=V$FU+gڌ_;CSb$Mi޹ qʭy-H[ MԷR]4`+d[x:bhn |$7z $*+du*G:(RSZUV[kSnڒ\@4Yb?߯h ۺ9=h;?uiָ+Y65KO=3Mgƍ=Ӫ%߃?5;㿅fMvf!{ޫ:ն[c jŬ~!fzgI9j 4DN1W8f>{$t{+pjYk?Q@\ F f{0I犬5UT_GqɞƼwkoDA=k{Sw<|RLoBQ#Z-, ؊W12AjouvJ]Itc #.@uH&\I&+k7S!ʱ֚땎-Σj*:։5Lf;U/-1>@BOEݘ~= ]w 9A(j*C+&[ޤ1 ⥢Ⱳ$aZ)PȈ*h:$dHhnh&f+6C7R̐0}55D Q۵kFX6'b b̤$(:M&Lv4WZޡnGZ&#r9ַ7l`NGZ[ r=Ɉ޹ZfҥD E%M["yf[B\>GV3(Z-֫^Rx:ؖ~K<Q2db:W*5l]ba֟@D'4M3 tC6.:3!Ď8[:1cMnt''ޭ}۹;ڨD~:QV\sYU\ 3ƬB8h"t0y[3XQցlph$9aG[7.H֦lDVUrw52:?F}%-,h$41$Q0 >D@BF{蘽*@ȟU&EDb1$f:'ހ9$f$ֶCň7;;~hX|p XR48,Y2G'Ҷ5&sǽi< O9TP.  /)3Fb;f."F s4`w@>Q 'fPd&aT$҃[Cly<&*GEeT`QrYzb CobWAv tPcWuSk3$J]dS@n0iRg^l[߿\p.E=kq].WmJoZ8'T0w*5ELEtusq>Ʈ9Ve1VW=^hnfGb++uA,IjU+oM $p5&۽N$},cv:jHoӎkqAe̷5xYPw="OxB޺(ژJ)J5i``vuҝE?w''ch^'9foqgXZϧn L?]s:Y|UsmQу<vO{FH?oo6En}NS/ڤ^8]xQ` 5Ɲ)Ka@Ͻ5&1TZ{ VU+#[+kD"3ڋ]s;{K֎ug#qeЪ9-s=R 0#5˧1% H<nVCع{NdUkd:y'NUQtm0*޷SWZ"7f1ZA"5Q1O1r.1@mxk4Z&[j!ڬ^ҀC7u^&dbJN]6]+veµp\{IQV)F+v d'5+$]irnaz'*m2=+G[&'+S^ƅ+zwہ+n 1ޢ^F:T)"j?Dւw-DU1ZLމPl@R$z;zq ;s^eI7`w'f꿉b-p(ITr+bطu *4Sq^97~ּDF;{Iz4rZ BXY/*v:r6zug_?=Ekny*İ{WoSw*\\e vG+?}yz/wgvd'7>3?GU=ֺAi >s]?D^wjS,wA>U9k%q5ʯsX!B+.0%kq^k@Y"Os6 ⌢Wl"۶Ʃ[Tk6@k7*$Mf㱬.$F8T'%H4 n1jMqr${TcXqAXG_m4Gː*:awڤLbw(|+I~7xXV;{AK{Xn? ('9~G p^\zCAbhV 15XYwmֳYڝB דUr*2ek6,\K"- ; Lqޭ Od&>IDwx4G_I?Q_"k5^BO[ 7=MQ8E eah& dkO(<}[NtfEZ gP4X%^uI"9D*h2d&K; j3OYu|`gR#ڂmEX4k" PTi S`E EN*6wZقN=5.7bnF_I#9ڴP-֌vճtzEs4ky?O_j"-fj4ijJ{f8 9qS3oeub6Y>U43*TndtfTALI} |Oy+0ӟBS ߌDGyeC[Ԥ285UuU\0`kߴiH#F+y]ڥ@(]xa\oq;] cjǽsN+mIm6OJSyBf ]P2jȓ+u[O#4KEk[m`+LFjU+ sv35S-JkuCoMD 덊Ox&If\Si7ԇRDZ}=kZ:i݅5jȶ#?j5eh dkWy}u=钧[_lpNL.r|+E*nU5Ս9^IgA6G+zI 2=*]N:{:=s+Iצ. Mr;z\YEK`(xaV !Kr1KW"ak1l3QZjkeG$tnxoMfߨT kz<|X#̾tW^@ܬiFZKܮV$[ nn(J^,ہE $H4j^rFލ&sF }<8†&ocr1 Mْ~KDPE3'5f&l`ц X'AwF\sFcAvm@k'n$œZ#6qPOڠ0 +B)qD.P ۄǽU°ԉU0k`bd"LץDc GCMn%kJi#ш+zȏA4}d{!x  8pxp\tMa1&O}tM;~R @;m~SDZEt?OJ |j7LUqBК+ISۇVk(u)BJlo41hb @z6 <T*S{зS*I'tQ 憈V.EgI5 7[Z'A1pLTYj+bY@Q_y3~ǵn~/h[#$kw&kRSzHo6SJ8pğڷ0CVR7{O\#oYd'8xf7 1z#5~$'{D&83]NdAmok^jrEu;lmM<*4EةɌl ڷE7Ͻ4\FSddV.^TzRAճ,ï""%II63n'VHYծ5{d[v*irVglzrkJ70%$QU>=yR31b*[$Upbpz!;nNnp$>)>b/USSn[Խj9^\kjRN٫F+8b5#ҳ$%#p$ޥX&;zްdnZ:{V3Lu $r' ͬg"sLt"Ni ̊7 ߫=L#yTbcufgF{ [bNkPUAګDTK VY I-AmIV0ؐIs5 Lk4^wRVcElq@Dɮk߄i2c1ןr;w^`&^~<<;m`:wdk> Wn1{=9v8?-_T3A^\p~!Wq^^8؍M?9Z b.r'޵*-J#`"15X5j@b|WFVq :lZv-Upa!J F()ܰN"Bqڭ8۟(~Rjۙ`f?$V-zocޥXlTYV-l!Z,[M5UV;JVT™8=+JҌ`~j˄1$;ku50\RbI%P&:EJldԪ zS[82Z0cz nG M^XbhZ.]Xi$n"O`+1:OTz\W .++@rfDZ 50g특dU DZ5qfRe1U"uңbz԰Q]^f kƐe*' 6lڪQ_z*]l[@#Jtm2Zn9%Hn<Y^]#>2sHWƩ|T\,~: ٚxn+`3Tn1SR(;q $~jl@:0R(ZQRMAkucDV(KN63[+ DzT1;U$_PDIUXDYAQgX%%U?MMcbv EL֌qX=P"㎕mA&AѸ#CjvF6*fN*H hV2 vA$FM.-\yP:bķJ,fzvۉڱ-\`5ZPjOhczBR~*k5L\<{DUżfUvҗ78s֥}!RӺU|&ܰIP@ W;EyڭPOT`Pm0mŅ>{#C'qFΕ\ߜj)rI^c_3t>~o?O+cMy2mڔqX8kW!0dih}Z3jae%S+YEmDR w1VpIEȞz\i,˗ِ7W;]- C۵r z岒H${TB=C]޷rp?jxW?']-*/~7nMGC5;Y=JAk+kxz}^קb1КSmSH@v&cZ֖OSLf+ ty5 ?hW-B5q8\P95Qe.baG|1tR._Iē~j:>u2QЪU8xӐ &kڄ!9Y@nUۤWId`Uvrb*d0]fv\rXa $t5+E@%2.}*kV6$rDFa AQ[\01QCART0A#`)`b=I=MnA'eu$ֶrӽ3 5q#pڼm V˿m0wj5/$"N}*hWpdU5jJIzc4$d'0Θ]BfXV5R彄T{VU+y&;KdLv1X{ȬSMeZ i4iN'ޠ%zP=.qPQn:Y57~THP}涇ٻfLYm#mYTVwTZ#u\}DAvl1xoMi܈XvԃYcp_ҦŖ(ʲ<ֱQLHŢvďz vb#Urՠ Ifv(39F®;O~.<( CLVZN]P[jL:#iZD;Tk/'@Z +S}OV{;[>< ߎ+HX.63#W zyx([#U*xKSt$Mw5{f۹Dڽ\,.v潜tٸy+Wn:Y\])8RݲV{'Z0{)͈E[n0V='փmec Z7m3H<[Qi],n}F[*,A6InzNZט'њSbMd] m{RqKDqW]T`3M z̏gŭ]  j-z$jMs鞽rb2;kL3^Q6k[`:"XG r^iRx;W~ݏ8:z]i]ser+\<*w Ă Ƨ^H\5~"\m$V%[6ք$V;\ό <8߯|a4{z>T,o%/qYI?j>F7 e6Mz9{4uڂ07<}Ux+ymҨX}|*4 7Z)=뤁6LT&E#pzRHz_rN`4YϽKN*q+(F:k5+P`z \ ^`R7h\%` 4RsMtԂY;wdd "+7p #TLSx*}^%cw*=(&7@fϨqA" N}mr@@ag65K3ʡ W;VtWG[,y}??NB۶5>G_oiU@9+4nfef2+5*MEdOd< qU3qZ`2:wu?ւpj''A%%__3@#4v?O ?LMfkDpqW#z7hCXȏ#u"AW")UBzĹɸͿDk]e H둓Q Q~Po ;6@E.k`h 3jjݢCzx}v^?i'żŴj3doHN<U"WI:zqn'Uh e} bRkuqT<SShsqX3i튐 DoLPAo1ZH fcEr -PфߨT-@`F~Tjvqh|y4`)jugp842uHHykpJ89#Hр"bsX\-!8lZKeSGL"# iAjEh(3ja8hM>*ĐZGS zSUlx(V:zP 58-Xs|2]̹zH3UpwOק]wxrlTkM۷:-b*" vLޭ62[iC1VӉKGt?QQ9*1"$c9vkɃ*jzWW0٘7Ĥr`@X<T|V`1@uI=s;ڭΥ#K*Ґ`$A&jb}t='q⵱4`(ӄmZ+!Kn;z2AQ"+IăCR#ԏCDF-4HbI+R\YfTdoQ#W+3h-==38FDǨMk Hs'Z309^I@"屶sSDUEoQ lb8$^PHkZ`h#R6Z.ȴX|Rɭ۱ROS܊/u&$AUD)\; +7ȷ$zFeA@1dY mTl~i^ƳTը '{78CHU//j۹a+[Hmګ2` IpgbB8Vʾb*oI/rrYF;TQx~`(4;vP1 #$t֮%X{"Vm[= :/IՌql=jRk$@D5%b:q_Q[W 0( <{ :xWˮK}zcӂ=l3>Y9GκsUn01k(sT)eXD(5|ǹ\P#=xôd:'u'z#UIQd ]"m*$ dOJ%'feW1F+vI413gfyQZ1U8\:6RtFiq >YIZ6b1ag3T$T]H TN"*Lrת:P*[ZEm5O}v /yzjٺN\/ >|y|_z[x[%Kp"3|U/~QK cmyNjpy{WW^n3_LOrWn+P . JҦU]z2Lա+Zy d`uZFq?5zs8)v Ӂnث#ߵnRnJRlLWiY]{{eV:2Ѕ:XnC5QWQu7bS& tc0\-x x'iڵ*=?Eu-BygsG1-&sCYRbLn&n$Q6̉>[mu3=ezD!X Tw^p^_Qh7uR1kprGZ\֬=#=yUwSAV`Mq Etڝnƚ%@ X"юhc^,y Gz7t7Νo{fq]!U?j/-NW d֮ `ZxwG?z?V``-ZDDV.L {e;{Un8 UhZ[TU'EZ㚊k,ۭs[`;T*'у(PR""qL7ӊk@;Ss‰8+ ;[z0(b y0uPA 1Ҩ=@9h!pmZ*RU w3ދIhiWvGnP&dwSֱY.\]+לhZbf4à榮-Y%@jk[C'$כ]q+ ;Vf9zJGWdu_v,غ2OZ0)k^ЂֳL [@'Uc6tʱuzO50JYL"XO }2V028V5P(WM&m#ΩLK'UdcNxY!9r(d {3u> -gߵ=[+OV`dp{/.һxǯ|3L.ٶdEyku`HF46 ӥC1ED^/Chؤhg\i9}Ygc=3q  qvj㍏3a]ey9 kfb<9қl t1:wW]jڮDR0*Ƒl]S'&ţwp'kauFlOoz95\EN}Qa԰nfRB$A1s1[DVH6F ނ&0P8E’{#~$[2 LŌщ`EfwjUU*Lނ,Im6E芤_{bk4JEdhJ1@7=h[iO@j;7"Hԋ:-B>xM+gjg.[^k;jEjU$;H=蚐PHhw5{ 2SvٖDt⾨,+oAç}Iy|LWxto` @Z*ko? Ld#q%fH\El[Bړ=I+K-29Ĝ]s#-p59V}b`,GS]5&BTzS m3:{`$pxe2h, bМf1Dh"If%P#C{P3 }ᏤX)xɠ 79uҢJ+tJ,.޼jhZ#8~'3KXtQ>2xoW_`q}?/dJ__hWl%X8-LHɫuX$U[P't6(j뼆^Uk1@Vkq3ɨ7Wkq=J^`ޏp&k"ŇAHwPHf3Wڹ Objk_<>ƯcѼ2n%B=ki\Q\btTW} ':*+6sW1ҁ5DZT iT+UG:WɴyBG??/he-&=qcO-D;WXcL嘪X޻6;Os]"Mr8-(Jwn{l$U$|Ҁ,NC~ڷDMlm <&hgrHmaj(s*&i⥧ԳCXstݾGj-2j5 =BKs3 VPRC.0?5`5="ԆsRPLOh)?ӟnnQ#.07[dIz]2wy1<\=#@|qX?#m|~[j^kF(s>IURgJ+z"@;>LGýq0?,zq[wc:CV-]V+tּ =zԫlH3BŢ"0\ڵ*wtQQ1uW'͛I"g hWHjm ๧R-3SDMi}11/U#鶹jΪX4W}7ϗm/y m!Aa \v#l[v܇2gWx-HC]gZV#sju>ܩmyECA=9E\@~hcA $.oX%[ۚ >ap@-w7FݤV7\n];|VY:4ާޫh& SbZ0 zGC]PN{Q:Ԛзnҵ#FkM~묈"y_wU^ԭU~*ka^MWy39m8nRsYZEE*LAM+STތLiݪTumM5)"1E dPjp 1F #nIl(YZv@z 3E`w&r(a\ȁFq SA\?sS[ F)ڹ5ЀqEO ;\A,djHkb5rh&+v0ڪ@p8/*O յW_Cubbk口LTgׇ;o u$jtWax2}#oK,M21z^AETUc7]fI$nV8̌I]yMlTcxy&kc_ `WY^{HXRa]eqP]ep]jGٞ*Hd4jŵk`IU*lg^C^U ]"*`=3Vp B $h`h'N{wtn85[0} @@L@*#R`rABѥ$D!+Ԥ/ft0kƣp3\|U>ozPs_S_yZ|l<[_ 3'?sVн7Y'iۄ t5!+yo,MQp\׷^d)i7Oq]ㅊE]~dWAUZîZ_}*s"-fpigP{V!wi^ԂDc-L\-ôip;ʫu:UfPjd]hNG:n?6t'.xmإqԴq;ԷDU`BT^cz屰&*+IVTsјJ#fџwt`M{̙hW<'FE~*Mz_]sqTۄ+W.|A_m*nv=)3:_@-\^VM ɮ4iVEaQD!V/w1Sj=^oa  87D*Yݥz. WyYPk0 ԢsVpvUlY@V-AϽn@"" ("yԈ(+jJ'VU˛fM2`{fgnHa?er*Do3hF2s?Ҋ[0q҂ k(.@yDvJܸEVdkxǽ-hL,&MNl8$hhs|ѝU0Xn"Ξڶ gS@` q\{NϷKM5jqRqZL&Q]R=={n[@sލĭ62${V{-ښ`lwz@˓GnXmDkڱ5Qrյ -S\kp 1r1d$El2#ֈlMbwZ1Vy+% ں9=Q֭,;}ꐂugM54iX-jh:\[":T ׈۷ln*7ۈ>?aڲY$N5NVJMG9tVj?ce;kqxrcN@1ځ=hLGZSOiKպy/2>բ"fa`4ԗ[֘&=$z&=&vkODqzֹ֎a *V,T` uwI*]Ϧ_}[jN[ެMu'F#H أE"pYvA]W|K`,Z 7S["y۵~gGxŷHP*_p*+u3R2΀54ji- Dֱ 2ldheH?4g?ڂarOf,nB3Ҷ2Lt5q9_I=pWm;(,uz#\Xܢ(+ydOZJ5@;z+׽eKp:ŭdZx dD5%T2o9=}߯޻J` WJA-ӈN\TFumvC`I9bUV0~Qq@ʓ#l'n _(қgYW,ݲu'F@4:2HjLNXȠÀ"BR~}*v~ϧ~iK7zu~LO w/%#˄M:FC&+Ы1#|n?e{O5J\lԽ>9mi t5R;޽\M=( IG5ǨZiwWNepf+NUd$9(j\;sUɵ3qVEoPK'xQ/Ƨ`c[khzVH,iea&zJ[r;աjo-BqVdđT̿#ЩڭEkr6r*ܨVl8۽VW?R7tŌ@*+$@(pW: rϓ3H++e#lq֥(ӵ#cDv殥&ȾԀ$Nj+м\!Y+X_&{m"bx}R ;w?svK^I_C}  ʥzD轅qՁQe@*>Ms#y-jv#[)__ƭ{2p Q|+R@ N9`wkiz+ n=u8;jȂ@1Mo@5:6KȕX>zـ$CuVZ:@FA}U56`T飱nuZptuPKWG6}2U Ek ¦zw jk+w{&HZW |YCt!WRTG,-B'νg-%Z#Z֭x[Уjx7n _w̑|V>oRFYՋZ+$)#5u L_115vP2L~)Vܡ*:cLm8^︡Tq03ikOe>]Kp j5GS[uu*0O߽n!<@A~94ZbS--oq*h}TW@}TrVP'!ONUv +AsjYm7(ygOa')c45[SI R*Lj;n6 ǽMR2'n Hޥzl!MՋYyh襻|T.,DIcSAb~hټ hL`KVPm<jE$ܟR5|?8ֳu`{i"mSkbpx"9y Wiˍ}LR6B$UBۀi<Ws>5鴘+p<=&D}KG$WXu}#jHG_s]c 5hKLɬ6F9hڬ=<bDA$I^fq]"Q 2 38~  c,8>ށ8P5A8@T#8z'w_lU3ИBbUiXW:6wc]cG]b55*5@e$$cjڤBKbJH2N(Q( NDy h|Z!sqrT ba2ꪠ$zcڲ &z w՟ p9}|A[g'\׾zl%Xzt%'5Υ6JQe@RՖcϧG˦rV.3?V.xk|r;+xȀӏEvppyBwA}h$3YZ`"{qX%ꁴHjC]mŋĶG^BmI=+(WCt"gj8rd6Xʤ7 `U1m22} )@mPHT1ցSv@Eؼw\TUFl6H\-I)k=Y1ۊk1&" n9*ځZbWbݗ cUk0@kqO^#` D4 RFdU{7ԭYG7AnRJg0=꽏V= dF:u6wO(Ti\bYW+VL8ҸX̾PL]%s by5zDOJBi2iUܙ~*0s3<^(ӷZ`e8FWpr­-0GHn-dS`Djn!&97^&ު!vU7S5i({֦ZkDLf4:TK:VYR({؇;gb«< .x;fG:aft^1$Z1x! 8ȣ{R.[Ys+ A9A˸ekGm|uP o*a:2L(}Gā!zѦӴB(ZlzsꙬjtQ5R%U^n= DjN?bSM={.u☝Vh-Fk6XϪebn7BuCrbҬTFuõ#zjFqP9_0zMe&Ŀ@Yԅ;Cl/Z#Ճi D`G;Xoxj# [I]btDr`@?s&OsFiռ xO5heV}f4*#/CS ¸WM]d=~~zqq'$bmP3yR t+ Z 1cV(߷:vMlC'[lFfS,b,X=\5qǨӛf%`q]y:[su9MU94f9 y ,GVު6љ& 5hV[c]cRdh[SSgF$Wz6{AJ VC= (c5 LSA@$2U J۞ 9OJ$̊#stq;)%Ȓb"D ȢCL;azvܖ$U`H9Ԙ@rx[v@kkv{we; gⴇyqFS0HMNjbԓDT$јyVr{2|N P0*EI%xؚbLj[{aRZ%3~g(?P| tz+yfH( {JogZweR.Ypyn;“ҽ??UikկNi*ԂP_r>9/2q_/~ߡLyǎY;גwc4cV:ט}E[r#޺kkoҠdɮ򢸿s${ s^{:VTq^kLқHD=aܳec 8JTkJW5& ;qUOcT/3m1X_7 J e6cLeOQ9&GjfXi0W A1GqǠ? c1E?5GAcBry9.ĪW2F]plX^ՍPŽS7Qg~zVȰEI`~ߊ{rqnU<1`Ɵ_+Vr1~k^xo GV+sd_+lMcߠM,@&΢[Oyo Eq*@"Q36~/Oꝭ.qA3X,(QA0}j]k9$#bT,#WXk| W?ji2`TaZ1ڈ/I"("URL0&]ZŎ6shѸY߭ [M KMCLA2{A%qՔL93HlF13E,mq+ si\oKuUAYwbk@7mX|R!d^lVf`pzPI#'0"aFGjnChQ0 ,$J YַD/GmZ>*̑ޥql JʺIBi_?^#]:\u`_Ub$d{zKNF#m=VVU'ljpmHQ^$V dTq]d4כ W.غ8KҭaY]-'c?5z!;HNc:ښ2xYcqj|(2($UJe4vܱ=bxi$Et>9'޻s\i>cz%yq+mHQ3 w9A`W;zKlG q7 OQkIB!€N01X ?T-rc ^n^##,`OHF>GtROު7Vl_܎լ3^Lcڶ ׯ* #U)J$J>y :RI3=:բ5Z~H3UYn\DX-l+tEXQ.ICѾ?Sl*Xdg=ڶ!O= ϕor*X'S\m{kޖ ^j,1vWnm'{$On?{#,b}굸Ϫ]uZAolo/1 .o^#m'vGqY~Џn79`OF~Y]v?֚k||Y/6N;qMe7 vn0 1z:&)jpͦ+z=qZ{֒P'eCBs[kZf4H/)SᖭٽpISb?!U UEr)p^[pJ$~jԼ!AYP|# aA. ;[ރ{M ȢkN hAomxM HFQi&2ffD V򅭒$VCV9l0~(+zTumjkZ@S*"ŷm ?ڥQ-&cT=z{d2QZ528W$@&]L{UbuGQ|5r9ڥ;U }c5|@bjswk&g#[j3HfYB=Q2zt Ư]6 j㧎;v:=}=;,ķq>漝}=һ/-5m#s+6I } S3}n]v[ Tv$wK7_i G9 psV;pOS#ǘHҺpqs]r:_]^Z;*`[Rys~_x'^^D|?Ǿ]HM\U.#=׫漳*Oמϰ OQ|~ns^$}ߊ|bԣkc.',"\'xIk xzo%w[0+5ʸнx:uY{8W1NwYs)$^Y;@/[ʫ>EUgۊūW)>M$Lۍx6LcH=k2{gs}n!Di1tl_{Tmt*w'Uq䥢mL:5/*Ӆ+n 򊕐h^h4LJHV;N#Pxr3ڌwIeVb-m@@LȐOW^~㠱LD0'_swOEgŝ&^t>d'1RՖVJ_G} UeC#0d?΢ߪmH$ ; ֧(`*C,\[?EʬLw5r?$l}KYlUpׇ+Ou۩7#Z7϶M֕!IMwԫ6 ㎿5y_nj5=jpz2DOsV a3D9w80VcpV4T w-&A3ڤH݁A k(,,!#}_{ֶ6%bꍣR/+AX2AA[S*Q|JëFyW.jBw@A`w=h HY1344Kz-ؒD@ A?)eT\$Msôb ux5kk(Ku+:} e9*xERIQ_6ױf̶Ҡlh8$٠1nۭ0r7hLb^kcR[z8%NrIj-upةj葃yF΂0?=. "T^+y%"=u*IUmfJs# x5VX+]:ן|rѷ LL5kPXc9ںJʴ)5L3, @v`րoN=!eWMV'5 ^-~j7>*òuKlO5i$cjAR%QVj܆f{HYZBjVc+% U9[62f5NJ$u"MmsMV%ot`ۊ`7~.YbrNj1)'ijخ,zXa؁sUCf-m'NB#ݏ=Ț`~WPw jq~.!D;'[++Kþ`[3''j1x?zdpy6Tye_ Q}UɷکV/po賘N amnI9iA.84r)ցwib1SOw~+mw65+6WY~ @?B5Eo0bQJI=hA8hXI#(|@1E;@|3KJdpMTebx؀TtqWu_XpTacR+1^gp>19^_;urN$]=|10*ew6.m_w{,Ry -M.Ԭ]Xam$w"uvYҹUPX:WxVlr:fu $c]ސhG?j%%b'b E[5,j0[ۆ]MMLLH7j֟WbHfu;z(@ ʍmC<ͿO95+&+ܯw.=3q5$_z@Ӟ}9g tp:i?^C:SYk'`׋} _W'zu$jq땃dc[Ǽ0WHAp[h{YP|[J?]qxΘ4i_CoU\$Ck Ԅ"c5f5!޺D*,? {Hݧ޵r<{j٢-wN]$5l;Iv,O=T}LH4Pek+coCfFޝBU T߯xGz#Vt-i4 ,Kɭnx`Z)rWBɎ5VX`q`ROq]"-\b}o+nr^YgxD$z jqxwtfO-DsEVL{t'<0m N+9`awMeUq+HBO4 \1F!~:ѩiZAef&T/ OX2UQmV8`(TzZ ;qA,FU{5,EGIm8⍆aDS<{fM[{XA-ۗ?HY 'Weg]ΰ>bBĐ#梪/Գ~zTGY)DsּJ !U|}>}4 -V9W}&BA#5u^oolh4ּIQ[FXNb-p?Qx݌r*kSS~d缓]=Q́s5wmV"Sqi?r: }fҸY]6N`r(=2I斫aQVJk'Js^L`WISc۟ںcY/Ct8 u ǚOd }뤮5r3WIQ`KUKpinɵ"&ѕm ֱ67~ƌ-*lKcs=(0 2{U_cҬnXuQ6ȓL9$J؝ޔ9SV&&\'TʧuUe*W~ZYUcFc1hS&)2;Zk1fF3$ԴzPn社t'ײ.p5+ڢAgkj 8% C&3穦MYS31583Imxwz#1w71jq!0v_P*ܹqDxGKh:9Čbn1Ugq'&v&T-u1GrG/?ҹZQfsj2)~j*d~cq{0%ډգ=$@h7@VȚbmcc 1F[GՖ@IrF 9'Z|_QtT=-h- :mR{S_Ӟkl52)%w +xi?>+ҹOzFX#5yU- ]eX \ݖ4GKcBҏ,CU A44|vB2v5r9ZKWI>σ HCV'uhV7bh8Lsb(Ff#oi)+M1iקlLS~Ջ b Exߏǿo>n wp U =YH acU/~+>V95P\@0E wFdy< =M6ntuxfF$+O=C `vܼ]{+)Uj(@JձlTZpk-*giqza1깉]4&MԊR `o2 {֤2I> PA'$b9 T_W?lAY 45 քQ#3A1jZq4;1!Kd&D ǨIC)X9iTKBfy,0iɊ/*;^GZ0ӀO&*Eahu 9$ PT4b# 4=M]:c8Et&R7~ZY%U=*1(ު%oHU4[$5P>Y8Psm[d=Ih[&8j̀\Ljh()LSmdH+ $mj~; p"2:zubb1'WI?eh#bQf Q ։B19mP Z.] W?{Υ8/=@μ?Ϩ+-&e[(sDr$GA3tαA&G*p8=sY[ll%}'ΡZF]8TSN&l+n}Xrc -$40@MXm Z,Dn5$ A=bGv5ޣ3>uCPϯ- ̆22ryϋxOőM:̏Wǩx( /޾[xa|{Aj5AA*j֥I fj'm<׆rH\Fh+bdvyVKǵth*S>`tGǿǗ}Rȶ3_WGm q^W}C{D,rfT)x]- <IҶԀ7OWfj%<}QB-93UjIa[/ 2e\mЈqQ]dmmL=-tƍw3\rG5=*FF);W=m󸝲Or*g>TZuz? SƗ\CGa[*1^F$]r]PGH{29&[ICU,hic'憐44E5 ~jkyY3[ÝCxڷS%\>Se+G3]%M]ԺT>\֥bO:GMgM.!Q >~\*6)3{}y_Pܘ[,N:\u;ø\yƺ"[XI3'* Xm'F!Ij`qF4kɠ~Q--="ʻ s9~>,Dް[ȜQ+Z]_$UzӺ5m08sڵP2{UΨPI;N: B55nw™@G5ۗzn;c:F_HgskvZREsh y9oo*޹ Hc:Ԇ-$GJ O[.͑%[ne.~bh͖ezv˧ic%Nj^wsS1^Jgi( fyD,P&ki-7,j*U;ʜɑQ[boAZ];99N=ד^pxd׷q+ZZڶ-xΤq5%Qk`]Š+~0;3{||ORoj3 w쿗% G5L^x^[Т9H<4.OVn"GiclXdj}`]$s;HvW A C3`z u5ךAXzq˗L}mT,gz'QߴojˡYq?<ksujRҢ3x'\l.É9km#?j#oUfS0UzEM6Y}='W;C?gi/"687\`7Q_MZUn6Kq}/Vܱhl1gk9c}Yh_]Pifslf7i@w3P0ydX,RƊN$.lDS3($wA u-gQ2cڦ02Z 'hOMӂIl{"h#ߛ?M;@2 {QCYbݟn$BW0+(1{7H0?y30d>Zyzn\ y>} L$}9~Hb,;VIW㾢+Ց}JG G.=ղ%Kّ715HzWOd]zJ 3U䊣M}i B܇ZIoj+pzgP[Az96Eu+zyx@G{ WdIRG~r2.ɀcJ1q=qWw%$LDN!2$0sz 7[EM@E \CPL$>h*[Dnԩ4o2}@$vk ^\؂z~+>w%m"{V@#&n{G&3_ލ r3[8n{֚`nB15pSX=cSʂbL#h}UcvGdpjE tuZWyXPH䠆 vc(ތБ G沚IKBϱ~9v]b*`X抒k <·R;u 0h R{҆.ؓR9(D s bPB@Edځ0 LVpB 7=ZEn,Aށ܋$hM*T},g?4e2)'3Q CbK.dMCށDѰ?c':XKq"NkbV-\B'WD44g>IZG}#:J{hn9U35KuA}Y`OWH3]˹nLOsF7ǹ$H ?m _=~+ס5uFAɯ|w?5kFG~̫HDԨPێA9YT `#>3Ҁ 7P($,tI\;Ԃ{H`b˱ ېA2kU[j×6L(89gιg197/Yס]AѳMYFMBښbU+[WOesSVCZT9V5VI.IR'$@EP+ۖts.˗=!G޻G*\{zl)<]q {^NmmpCAz(ޭ:z{ѺF@X;DVgL$H[Df21TU8Ke#XW޷.P1 (?HuLmOktvZxƟŒx=zQEF53׋#<U&O|?_K;u~QY&}}= Od%X];sz%yy\k3n}R$\F#S'bpGX/(Tk ‚2j{2eٷkFEwqvMg=5+Id fJf]am9U[жIAڵZӲFvWt;#ZŹ̑޹WXjst^0qޤM_h ȴ=;Z'Bb/CR$0nрeU`ocmF~k[JMJRI93KIUP5NV2zs]q{[`t(}z%yV"Edx[:=Q N ?]w[P 0>MzsG&" C\F:WHʿ-05W(z\ V>_#፯ &(q_` ȯ'_y>=~q֥v7 - '$T.G*laѣ׉eNG=7X~!k{'uZ!P2+er<Lzz_= k7NC-G{\x58/1F?tEC8ե2![PGXGJ1ZCdum"n%;wdAqqXʼE[15 =G^MZ'5eVJH'D[n Q [$ ݑ5`ּ3D.v]zU|8H ,j4jk1s+py\]e'|ϧL}(ܴj7 JWR$PUbKȘl{-DfDTZ v$YjnՁ5 t"BjZ9n tS!>ղn]5Ӹ1LIo 1&i7C'MME0+"r;ѡH=fa8ZK!\DU@X4beEs&5J0J8T U_FՍ%C q}Vڶ"T:vs#McIPARIz2+U 1~hh5%)Jl?VjN L ,0ktHyw "MHsijKܾ63Q?Jt8 f;?_shYGk׍{wHP\Gݽ@f 7wX,BXc'D 13> |(hWmI'xzSxH]U5q;r,i x4kQ@94J^pPpA@@;>h n)(&Q`P::aR Q]ӹg"0,G=hI1r +45eN>i{F}eeUv2nAlL[1У^hD283FqLNb 9<ѺÓqPԞrI;3PEe-ryu/iސ3ɩJ*?xmcq|/<}ozW\,@_SуL P["ͻR͓U[jfB ~kÏo*hK!$s؎l%sw/nDx]q}?wUק ZWgdgP`xm.H4VpPx4,"lHҪA;C,UHc 2G WIf+Pz~jIҷF*I '42#"~F w;%*h4fh' mzw"k_EPeTZxx鷠W+W'8H9Kɷbڠ="tj:p~=$I8p^6kKzO=[E Z8mօC@Bl1$s 7+j. F'Elci{`箘hb'Qj`RgڣXla8RhZ3i1U.NĀVu2*NNLi=4=#5Zɐ@5HKDFB<,&`n TCwKi[5pbLAmĀ8?Jh&ȶI0P sSj퐪CXO gI[mI?5nvDὫcF^mQbjLTjڶbzRyg8#1k1w?U:-7S0xh95@ՋpްI\'k58d# +ľSyԍ&T`}Mp!YvßWĻ`bMu ̽W+,ETWSV(yAQ39C{L;Iлmfmv顨 =M˅H sA% 3= eTZOc]?:bn!v"Oq^_5z?_ d[UePb+ wjaڡi`َP؎U$(*YTE+qtҪ #xZAg&*(_2=`Ӛ"txm0>LUkƾDWuc~C"9~lAfKBGp~7'T0"N$se ;2gީ§oDb#h-oQhAIdmX3nuUUo]bjL#w{HNDɚHN=+DA`*4 5C$ւ[5?&4 niX\f2~,L"9bAuQEaEOT5-g\ۘhI(Td&V'gzD^Jۖ@.Lcڶ2C. 5I1 ؒsjjݛa$d W4SҮ&ͻ sZG2ڭ En,hʳb;5e>O&eK1[URYjب9ִ( ZL Et}_鵴և2d~gT |Z6J⥫ }`4W:b$|jnFZʙ3bv9a1޶m *\@,bv 59W}bn(,A_I^GͿzGs^|%r:4dkv$Ojϙ4t?zm9KbG\vT=: hEKuX6> 8DȮ~Œ>¬Aub׈W)U5ă]yuCq ?ֽ4'xs7zYnwO+ [9? xڼ o{כ^O ESv}zwjK$H'UdJ7w\0 ziu"Ә5COm$H35W]ĐUk;݉"FZr[`k0L`j`ke5¹coRPI?jE$kQFkUW"94G_jhkɶIsFk+S7.٣%@n6ƵȠS#UȝvH<:liPQIީy=5NVh۠XmQ-5<uy^6N+OD`-1qڼW$ApR;OWs]#[74·qsnE:C$׉nmqX8^.#l!깕$p:vyĪ]%ecW6]%f3S=+7F&4e&LjܞqF`n\ʞFLOaJ؈E[a(eK9#=78rNt$`MyV ~MpER ,%EHxIMPb>*h93ɊG挨?j$HJfMYm3!,KF(IXETH(?5(I=jK3FFt +KB {ub+IkXk 4աmh nK Ñ֭}" 8ckbkWNta`r[ߚG@``I#Mkc[ͻl0ʴӛov&'>_4H p~ki,_xk+6@> lTKg Z-cDn z e'PwBPbm?Q_[G=5M/뗋Ƅ;r{|n1m)`O^^笭F R.v\ "d\u[Vex\h&mW!JU%)?5*'ӐN:)5>tblaT+:mbR닀2fG:rd=+0/:3'\ @'ޫʼnciIHӐJ.gðogZDڍh$ss,f/;*G<+W z-s7e\< 1/3֩``bʉ]1qSżٰ ֪2/&ӻ(UO]R_ On"3^/B}K2L?a^G{ vşEˀSȮ}xOӔ9O-="#=+zkI/%ނj,M/QzʫATOuĭdZwGn&`e\$՚{b&Pf P Bɞ@w=h –$["Yt#:1dcPϹ}^Kޑy `,fx@o$*MbbAA^\:lB@n\*߇w5K`ؘק]FɜJc[ٮ]?9wXSd*cճC5yF,qECw*od+t/b=3WXLj[9gxVt~7#q:-wnk.9$prNՉ[59Pmev!|ޝg*sVkmr#X3$NjMjl+m*`FATPըI*,Uj`h`8Ta&= &Ibx< 9lr>(IcwT6{TЅ%I抉 $pNbWSEjUAnՊ\P?j&;dǚ W@`DPTF,W4jݗ sђ("X08L׷g?zj ]e%h 9a1\賠p'$5n^o$v׭};ymv" kxr xZG=O_b 'qVQMH]#^WRw<"+}G71Lvx{KZeǚ=Uø~Z>BB, ɏygӟ@x_Y\T~}^Z'#\]5 V8ɣckjFkȸwH3zj.&r1DIlsk;քG1뚸q/Bې `Ou:uځPY WeVV ҺGE\T tMVjϱUX,fG*93ɮ^Y78ȪrZF6FLbuaVYZ UvkcIUIX+F/m +pǃxgA=O'5q}>R!@ebD*!2q+>-r !z8auCuӿ*D }{x%Uh4CGOц"A>¢xNF9eUH靔611}Ϥ? c{J]?|Uk+Z3r}H^>WRKGw^5;r4V7kuQDN~Ӛm*>z wX=tkdw+@ڳzq>%ns"h61nlOusHT-Ү<[z;l@l6޸;UD+?yF+#nXfi$YF oN堰=q:J|'ꖶ|VD|E_}GkR7A`WgTSGU[!QkljF T3Gӛ)o+$[&zgLy;E5X儴r?F&1{SJŔ 9I%TtT?vADuTi$I1 =ՠ m$s68[2ynݻ0^h́σ$qVӐ߭ު9U}kem?qBd'ˍhxu˒3{W6'z_i޻JR{j2/}X^_jJbEjV(Ao6V2#'Vv)$qUJmzOM-CK+HW;]$r!7I#wVu6(yrxv,Bzj:6$u ϰn$n0ՑʫL(PC[KIj,R`oմkAԁ# 0$T6x@\ 2VԒؙ 'O1+"2O4n"CSiFڂՠ$P}MT^  Ɵ`f+^91Dzyf,(XgEmyF;z`|Lgh+ . w4p.V):w봀:klHfwӮw(G~kqӗ}3#?W>?5a_޾'Mԛ7{-oEdyVu &tz+^[ڰخXS!O}/y&/^_IG=޸NcSE[bH;}?iO<)-vi2~տN~L\QV;Wܜ~k߃bptA?/?Y:3?} ۟u #)1XyYcx91 ?z:F3.rA]Kbz*j{qڻ:q}'3]$r큞]cj ex5G ^υ V-Z D-u P|5WYgtbYF,JcX N7Xy S R{nK{9?jomVPH{V+N sZkaI'*#Ě囶գtWQ8}@*@5ês4=x_1&zms omajGMadk}0>X>Pf'ރ_N 8iw!-1+,D<Ƽ$[9ᚭ/_F<*qI p@묩Y|Ղq%85I21sen d\@h(*-[p3 ;I<-UpfͿOşnCnB"ul壢>0c\jbA^k55|?\wAUAVES7$Ѭ6p;Gj #ڶJNfm{QX5Py0F" j'uL9[ΠզZRaތL5Ǐj0J)$GZ7ޞrhHj* &H!Y'EŒEE5)Ef A&9lݷS1Y@b`=EDM LH3l1mǁF("Lu8Nc=hhNEu? D,?V+C$Jk{f+AUB2t=BU"q(HSjgq F~U#3x` z՚63 [ִ~jIs%iPϿjje| 9k[?@\?ׯ+weaO3_?S잡GZ>mYAm\bfXARMb9=hv*gNqКV9$G:1][T>,L@_w|N])q*woߕiYk{Aֽx#ϕ -=?T?}ݥC+5Y h$wl.gMT*o5LP]E{Q*p!{ 'պyHWu_MmNF7bkx']qELR >s4fN;W\k,(e\xTt?M0o6u!TugM*0+jm>dSBKHm{ST&7IMOr3Q]#wüMMЬ6Ijjv]ЏA4K CH# _xoxݫg^_l۠ku~p!N F)sLnOޘ/iAVBֶ*4ؼy_3Op`n#]+_-KzE$%~3]W+;O"=G}_[`Kw?E=˶lyfgthiAʡ4ꅙAS]$Xm*2:X,;X~·Wi7~H5S?p bB9F)zɘsi!t扰OZ&_x-#Z9>5^bC™fnoOaT)[q$h!€O=Sjo~ڈ⭊E V[ꎢ` YPms]qO d%Dym0 .`m#>B2 [x.[_dܶr{Uj]әn'ZZa9R +-tyȧ@VHu)2 '޹Y$tF(Hc s0sEA\^}ӽ帲f=jEn-05:de`ğ6\B@%I=y5VqYErkq9+OqMBhFަ.qށ\ @ @ken*j,>$O|m7:m+ _@E7ߵS+~ʝAS !IF3xIi>iS@o B2~TU-no[,7hz#r5a8txbȋY- nbAI$dc> D1uxC_Kgd+.cSm>n70py_x81%fc]Q! z#q+u{U+l)޺9XrD`v8X{DZ:[gKST5k`*c"mwZ2-M'[T)`juPy~*#<^[N#4KWq`ޞUW&81߽hb}4mVS($TfY}(`IYkl5 7(ۻMN: EJG;ۏP#_?]ݯ\r_J@0x΢v/i\(9 ffdžKs|=wW?Ē򲠇vVrSIy`pk7FFHS׉OF؞_Z׃aZ/ܓDɎ֩u W< ǖUХ:}U/nxy_I0J3 7+,y[hL8ھke_0k#ej+ss]+2+5cE` k^\7\]cUZ{&͠SlAHUf`1+,70jITz|mTcuW9َkUeMhR. qu0RG( $p*ఉV#Jc3'ۅ~<.ib,r6ٜ05<ƿY7IR W:t챉GkZJ5!V5-tV.hZa0P MuGx@lbHȿH݂**nht\\w\NWz_8F?ɟNqnCE`'|xXӰlg ^ghɍsSZs*LS*״ŖLT[`U)n #ڻF7uV=LZu_\xKB ~~"^3 =$'z|6Wjubʠ=UjfDj-’hpr~تȃ[Io3rPhf51CVE'jmMuXȪTxW*N7$Ts&0sրav@A4Qr434lLڅ-uq,4TIG9if f@&GJ&H@Hч j P2r"8 AL*ݷPKx=?4 $~(ނ!;\("N+-f\"V9ܟ3SWjf%b( l;][\`!;-ۖ8zU#U }'yl@U16M#[,ōk^Qֶ1h}=\Tye>Z]iT >֦V6Z!+*:_M[ګ |7ƿOAО5}i[|Y\]!,A"(X-śD\ډ-a ?JW`:U?TMw]ɶ ;WG=q+ /lW8ysָo*s_пs_ο<φssc5Y޼sJ9 sw^gPhZod5}#{s^!_}?O;϶5 m&|}:,]fz획jXRӑ]uw;ƣsTOnkq`hy.w5MvlgW{s맫x_ﲩ &M~ٿv+?O iyˌax[mx0G׍ ռr@eu8Xeē^nn}g]'K0 +le\ *DY i)W;@RQ.iVȚlKO[q=b1RIbL\>ij4M d0HU4j!uNն%zG޲_ vsL}ëSv@:W$l6ۀDH57Q77kjH☭\}K~n8{|7ZD?Ll_K$ |ߑı7vWx6.~k}N:(|F6C ;HT I~ДګUo?VCkZ1I+ƵCa`JW踿O>, 9(劷n>P:vD HBU,afDx^ѩ^BSQ]cJRP zV:E2Pm66aOtTMш9Uu6v?4MARH= Zh!L4sɞkc F?5H]F$h&, lEgܸn W"k+Uz]wzt`XڭH2+qg[;NTD7oV+jY@VUS19Qlrk[@ 5ߗEbF8W vp5 JZن U1"gTY++ g=+◞ڰ&$59obW3z]d`]Gn7'3ڹڿU;hX56+lm< &YUXڀZ=ն<4TM5  ހާL{P@i1f&opO^sV6'x=:.0Kb'vf8TViN7 d&}c[ Nv,2RIj1rQڰH $Zc FXh`$4|&gk U&bNA `ǵn(ZH}b. [{5;>z(ƚ÷`F++lu6Xa&/kSK.ZgtG-m$\ifW6=<\z 8|o/?ox6zcky_GvfONƼ\pRXdbx8=cEt7~0׮;jIunjIiTIɬw!G^\͠ v圕Xnjb7cl-wM};pjf~H>D~8ףZߤ{׷Og3#ܪ?x\ ȼHȮ>/_)  >?白8#-Ԇ0CuW\nOb3]~걤YԈ Sy5|P[秠8uq\xp"U@^=[{@,Ү_rb9ןFαxGc =k_/:kx_63~>k/ߦƯMXj%/_4*2̯?Q'lbW$c#Z~x2q?5JyDvê~ѝuŸ$Av׮};6H@Uf8mPv]OqD^܌#s`$YG0fݬ/l`>hMaMh\k o9SFIψ ?M\vkg=yg;6,ɜ5둻kjn W*u (HSgk1xurDp avYLjYqpxXAA;AFh0Fri7[6 O+`|_-G&/-@ɞOt<vh" Y 11 "Sށ?qEhlچ)y=lI%:޳ڰ ?hy)dZ:1h(L(JB2>GpS?4Fh(F `"Ա<}H'#<" ޷1c5&vPN*]ޭ# >dй ħKN.A =*6mzVYT,ZKґjH,5[~C?ެ!)m=/#bqңO- H+|/|2X rku_v~6pTkRp!jApCMdZ`<>aTcZQx q[RS-8?jY0OBڸv׬gުk4k@=?N-!l;,[$&(n 1܊CuIpkLT [.@!Oj6+>ԕ $\xbOb֚fkܶ`+5Q " J7$ FhAU1:jjn7I/ VIi?ڶ [ b%v 155[Phפָuŋ:U@Bl0gQ%5c u$yU+۴A wʭinvʷ4 ^^^V/5dm ]ء]zta-seXD"b)]$U6 ԺcU7`jq jZDpIX.#֤\12h,$pqheM~5Kh{ۏ(իn1Arʋ ~j[lcԏC!ȉ=) ֈ>:հrܙFۣ~ݪIqz˒ڹHĐ&պ"yML% 97x>̒cl|O,}ot5;9 {cip3A,. fSRX⣨FYHҽחvHc'{zcjWnc7\[A)~>G7lp ]%Mp-b@PX1]esxӺZr3N_/?O6MDsjG7`N*XPKf8UEoUmlftbLf;W.1ß oV%#+k9{Gs!vzkqg_aj<v,atm}ՇR>5欍FNxǦVB7H5n5;l sT}J @չ,۽V9B9qu 'Yn=2D M\?T TRz3W#Ww/If=>jT]1 bi؝4n%zzƏl8l[ӨYT;Ojͻ/zSu^unۊy~DNxױ};O5'W^y , Gqٳ^uۑ | >?^^9Xx(LNj=FXk2c=r9 q lIx{>gݻRT=b.; qu*6 W|rƗ̇<~Ej3YShpzף2&W4WTcֳ⭽Si2nNl#ȟ{>UV>W亙_FW}a Kk&Iɪx3^N2#{W~'LyֹKx=sߞcq]zѾB2`D #U РRdwδZ'=sV#X *+4w }Ԥ#4 $Du lj@?jp;95CCHO.aM_m̝D\3oGOMڼ~JOô.]D*JEx{$u Zp{Rφ Һ XGQޠv~hYPkZPN0@}b N:Hj 'OǵgkGyh<Lj,s1[ۄA\-m8$u㺥[ Ӛn_-5i@xJM:EQjZK[ztYA$+z$t={Wc¨\-ufڸW\XpDq_h!u5ӭIګT](?zTӃ>x\GԞ%;,H G.6=c3$s^\:ry]\*vPMRVQFa *^dn@D`=_j0Y@\ 4nQ ٖ2Aj t\d0orQ[ ɫND(:y1IFb h'S LSCHhAv&D>{҆{:0^@ h a@9 l~ a~ހh̞*eP\!@W4fAiHRUD:QͥFFz-~j ʋaZ+ wPDֆ 8Vƒz(DV1n&Oü0+}?cN@l?P~>_~_xZ4(`?^{*湺 Pq2z1eQR2k"W,@=Lhgj"X{-pqʹA2OJ;ft&䯙VF_ _~g˗ō%gs~7zS .ZRT̚N=^^z cxYKHA8k}=LokA @>|?4mN-z{Byd5~ ɒIx{{>=K*ǹr[>~7+GE^{Qlj_WWA~E)i\_7w< Ƕg]2DRQkуn|6p" dtMiZVkMP7|UxI{GQGa[*1tv.a$1u?L([i85=xbj:%T$cy:Μ},k"K(ÿS3 G~<;]>m-Q殂..ZY$s\螎ז%ۈT!@ ך^k#3RBbY |TO`+5 'ia,Iި5ҌQc&$@JD Q!ݲXnAjEmEjmVվ1MSu7<͙vhRx{VLZ´TQI;Cp1DuC7/c]_,p?O  8zyij-=kzi=kAϷzu# [[MFok@>hִ@ U6Wql)$bkmuO6Pb uzr:O>Z>_rzڢ3$Vk^ %=Yjx-:{=1E-7j6k`@[gԋZ'Wiӕp J^tls?U>ꠞ*[ܙ''ծN޿.?ҍVmc5:zk/4|xOkZݍ$s_'z8 H^Z|,KtDIO\rvwl a`b8Mm (m[ Hª\*BmLB KG0zH$rkC'/-Vih?yX*T4tTdRS׃J# ߫i"aK`MxfDkM; Qpw lt:O EoJU09]Mih0L .n,:Mji@7 bG'tNG]0V[hj(-Zph34JôՂddUچ-$$dx3[$Y8/[7n1$I_oq-/\" ~wM*7BPbz[BNNyۺsP--quMi !E`\ˡjHA$;NוTm=M`VIM`(6YZOzeTMҰ:W|'gZQug':}zGƹ6nn7 0+WU4찵B0*. =қ">j mʏSMtG,+d"Y_FN&zג&kq5"֠)2S, TtOj+G["+.V@%V\fB"5N w ;@xMSԅꜙz[+2;[f*IlUË$EKȠҮй]#=HkGImm[p?wƶt7킒yWЍl, =lZ.9뫕9TWpp8 'j]1#m`:#]YpXz%ẅ@. "U!2af*)Y]_Ɔ 9D}wǟΈxSs]9}ג@ڽ2Xuxc׳˜ pjrVN׽tr7 95qͥZV#$){C 23bzOh菩m޲\8iǨxfy41_^mGjϬ|õ2w ׍}O+nͻ5۞+μgرC <\0u>m@'ȿ䇈xj 7ֻOꏪ|(95JO7^^lczŇ7.;d?:5ZrŷCHt%Nnr@zs{_yݚykvu Oma u<&ATR EL( bOR@ V !PK^Y=`RsZӐ{8 q.nPj/obWpI2~Etl'ͣ`¢H $spFv?UGM։s^^1Cx=wb,:c ̊HLԩvɐ9C,HϽPrC"Os5"EC Wˬ3z5E|u2$'Ww&{]ap.^.VVdQC%Q:"n=:Qt;jC2SC&ObOz}֊90#eI9өZ]%1 U$'VN؂qU!굘Lw()c"Ae9ub BD n wfzt]qAFi N~-H'sbm4&F3H "kBk[$qCQX?=OiF V uTty2rkP{v(-u4b,e lx&g.׉$U:~ճr&{w{4t]MF#A#1V5YIXkc oft~pX,Zسemxf˖euOѲJk|ğOb{%QXE~z3iqb"dRכ!֑#qhWU:f`T J]]$q뺃TzGںcQWsK[ܙ`q_?| f}bi+˩@ª`TO}~f?9 Wb:K]Z;2LRch 7ח?m!F?yU5zGֈ+!{_|Uee|Zoo<^sRMkM5v4uU܏m6x'ךaCDr3[7!]#*H+vP:Fc[(a\,z{U[T/=r9&kSrHhUYK$*@5vLAx6tڱmMn<ۂڀWz^Kݵ$ּoJɹgpI8 tٻc!\ڱm :P&Yoa1R-3۰mk`U =)% #Wg&ČN %3TUhk)xCI5$+I{F拮@<  SYkzƲ0Hg\Jϒ?Ebz߂WK7$gzooI"ݵfp~:k5 YT~ ]&=3\TOvަ8HeGGZ_>zXHj"[iFL(|SMXlbUkSaeln`&}trq%EOx:2N:ٛj:vV&Pr+-#V]U=kB˭I&{Tַ4W'RK\Ldњp,-G c{df!:զol$4S;Qw jC&0 X-{Ojjؙ֢3=@6;[=9Ήy8q>ۚZ4g5<5,O{9-\,}R=Wy?'XFy@>~*A"̓\t/ⷬEܳ :;]$s% \)sۥq1azV-0pn+`\uPYEFdž: 0 D :kw>QXvtU!^DZXsKpdui3Zh^ r TʃXF'h2ZHA+":U jh Hw?z&E,N~h/qDzP@sIER}Qè5{G.YB%X5Z0‰7%lfbɣqgN=q?Ɩ T\eN)dBeܽ @yi\еif G֖.HBcJnFɓSV oIiE4Zs˹wNx"ٶGYw^~1]k~Ն+/Q1==7q=k/`b:q^9b &]4p#'*KA7UkN=%-\px:me]E0,vs5}<_tWԂI[ya(%{Ic&`vf@cVk#[e},+5>= {l@*&gW+_wg\;P-Kֽyyv{Jq_W'\[p2u!orY^?6_'a}[E~0ʤD_?}c"sIQ>_".)6X9_~ƯG nzH,#UԢ ze;#!2@("^* LJPC bXkŽ=bM=Pށjo\NxNP}c8wi寡⎻/kR햷>^:=UTGIy{Եrݘx"EckUp=jsڲ[WX.rGz5$%OX0WVТpO5c׫Yۧ[kB7OϾ񧲷Cd8q&C_`x=Awj kB|ZkkkoڼWh2Tj]u:3G&WFޜ$^zoN F~ՌR͕ AQ5. WH|,A~kGڸV%H$qrN9 4I-+Z`k@je]<`u+R"TX2wjX{! 2=NjZ\]#Mk*VZ[sV1[BP"  ZB`:%̘l3063"Fe =9?4aN-'4  hhL4Ђrcڨ;b&h"`@F>kYLDV tzզm砣b&9=&UF tj Z@3>lvB[VLUF54B=;&7aQ5sJ(n%+U[ePbŵޒzYE1 14oJ +fz*EgU8=d`皹R[ߐ%D1]CZ$v8Tc 1''VyyC0E^s`l;yqzkP]6 8?zu PB2=ԕǪ 60OZK&=bY&D_bBSt歇I)1&B402ktmTr"`5 4>n漽,"fz#ٖB@+]GIOD$:uYjΌ=Wy˖06߽q:dB:Ti`eli ;D L5Fݟ[3 k~ƂF 3Z Q76$^lt2HH|Egj̨TCpJ5h%0p=F*=O X$ڌ2=h2iJ-dm9[v@SaRsVqm+6T @[8!]V@I1@, A%q`mi$VQs Q\ˉ?z\@0I2oZʷNB8-G<Գ:kX{1~Ȩl>$PV `E5;x3P>Pdc5Q9[.ָ_3q_{?>,nXݏ_?EҼ2󽔟Oa3^JōEq2L~Վg4e4bx5p>/]ϺA=)OS-k5Ǩ[FWx#'Oqtlڽ23/ۍts74?֪}oµjɃ?-d_Hߗr+*n 'o߷[z6M#{7jE+ gtq&[ORϩ4-f=1_Pi>Y,Nj>ĆQl0J> $qG7K]ҠZpdLu8^g΄[ 0ΦBzrkoMP @͈.3+ˇO1ֺPiL׳|sWI2<]76Uck'd ~13ҩ0T,URY 6vbvX4[;PpfOyLHST;wMgz"P; u>Ւ?P3Qw]Qk÷kL , gg$W>yuq(U߷yt lbA=|aejXjy(z\G Ho%G$ƺoWaR҄J=\H: kGY 8 "V,'2X'!/0F U`Ӌw3Z$ތ ibDc!iZQfEB㡩SE2cOZ ׋0 +5n}@}Ɩ㪫$k(6Iٸ sX!pʜf9_bTϼ!X0VKmZ 0; ǽ\*8F@>]vT_,LUB2u;FTZ$g+]dh-q^~=]v:mr^n#bDMrl;TWHgDka6#NՌ ֲ{fMt..[ dy>*L,?ֽƽ2*(p\#0DylZJYh'8G4џĜ)DE&{PY)4h$OJhfsU+(7lW*wQB?lU3n˜Q+!8bJJV3TXLL?5;{фքcJ\b#`T5AA&~C[hee8m& cb 7F@Z1?~DsY@؎b1rHéֱsMghF1Qi^nY@.|?ǟOF pM|Z{V.GbLMamܨw33p**3ܶX׽tʂ-ܶĕGr8ֆHn[Ǥguʊ3n@?]g.chl܌ԯwM=GI#+?э87( rGO_\ !3^ljTuiVGq-[[{Wl}mLyKQc{,_?`5 Ïs\|tl״,35:cmcAU#7WeZoWRºGx`]7g+1U1v͸M+:PASSWZm#  ؚE݈b*{_/G-jJ~rǡT]\虸OW: Mw|Z`]G0*lp5V"63h< *Tⲁ,g;2h0X!s[4fq޶LZzKMlaݾK;ookQZ ﴎûOFƊ-8x:ǿ.U?5лycph;/7^ygݸ b{o^ΦͷV{&zσy1MgJp+qfxasZNp1Oq91j͠ Oںk1UiOmď>ךcʾOn'v 9D*kSA V^4f[}Z#ZUwEb!R6 ޴ LHHbbdgw48g<.@}<VX#^;}0}:0 ,rGUZ#'ĮL`]9oU\o1qNz)wpbsyb1QBK7KcȷkNXquh4U@I#(( ˾Ӓ'iGOT0nHP Zj-+ee]sUuD$;y>zAX,n5RvaqVUKH!H@P rqqZ(z)Tw/پMփ|tyTYj^)dB$Vaع8tr+$#vt[Hn61ky{o4#i f9nDt2$t+C(8+*kڋ`—JG7ԟo*R>^?WSzނܱ$G 侺neo]|\-eЂͺDI23|c^n>Xi9W}w3\FeW=Ylk3ɫ+>x{U8ޝwӞblsh Xs Uĸߨ˶ ?h*SN#w5-dw7 [/v %36HOM=wYGa]c}cy2k9F1$ZT!׽`w]@F,zɪ?Crйl7Yիr_•l\thటG7ӲzqxO4n^a8bߏ?-ҖI:"̞}8]h(,~W__P_Hb#޿#oNgoB@O4^24LZ?oMK|gie &]$V1kxoYAgPWtPY/ "z!O܊ۗ= [3 uV@xr}#wP'&hdx`9M /=MJψA9h^o'X֯V,3|>&Żk}^C]6**ԼGTsHj8,гZ8y! Hyk^@I=HRx \Tm^,d9MuDMV9CA%M\My/x{- *Wq3fF1!F?j؃[G 9Vvn \ݍéH 6iH$۽pFFywB\Yb=;H@8Êh0@;W:i*UГ*U㸡K( #TM)ھ]%Ma-lQ^>~u0X?oz'k.\ye^cNAD,AjjX{䨷e%$ZʠqPd‘"]A\j`W4}OIY<{Mf%ђUIX⁍IDY1Y7{Պ35IWkf \ oT)ݲF+V%ک!^HګY|bBVQU#=(]V L4f>;}TXDP&ZGqAGH=˴-L$ XfIVDiD$שPECށ"h#zGZ AFh&CI#s @Wm"IĒ$|HZڒިU=/+e`qz"+UjV5s,{q{H$mҺDbۻ,Z``7ngփBP .Z @=xmk5~ߒH/mtT7Wum}._(]<_3WU-i9??y٫q֦Ql;~H-`pb$Rc8Z?jRAk@ q]"[v(M%"]Ɋ2<ֶT ~* vZ,XKwU"y(X0'){e0qcLR-h75%xďEn8>ӏ)G'<*yG5=aUyW>Gxs\ MdtNͣX.L[csxQ`30=`|ۼ ȬqAN Vbv+c쬪3] nn?nwż@+1@yQkcoȭ`5Wnc|gQt2j]q) zR!#+uL?P:3lqdA OzyNo״.P*1u#|?}_Q ?.+UNH}9/6l6\ڲxw6=גȊ'/Ly7r49|׈7AĒ'9W:z[n=ƹ ̑槮\~oǗbQOdWG*[#VՆēۧ7 TRq޷RVYL}B,sֱNx4o ( ,Z? Қa84Et gE-`;Ujd\RLf<8t4KqIʚ7]+l IeG3y~Qn4H=k Tk^W;]$g(,P޹U0vڡ!1עFWҋ*.H_X!±_|)?%- OZ1Qp`oڪ2cd5NUU$1{՝*VkGp?QZUnaGkW7ev$+6Hj [,X;PKaOCFH"S <ނ™ # 1U;5NV$n3G;kIչn}}V4s8KaXqމhۅ#M5Yq%|dm 4M+*nV,ظeR 2 e uQin:?=O5}Cth޸.Ya4M(kEv$bq!ۿ*,r' ttz=G)ћ\rO^Za8 l*i;ӻZp"Zg'Y0>]Iwzޱ~MJң#HJfϨ jG4j>1[ ךEiJVAkm˷s;D99] v &dF(~ػi+ou7Xڶąxnu JG ~c?z_%^mV3;ViiI+=WUTzWs#|%O>|ۥ+ڽ{Ut~'4cHMrDZ^ӛ  VG5.G6FXwRXRFĴh<C;  |CP^Rl=jboLQqohYE7ȻXB\ x+_|=K1.WLfSMp/n݇*@u=k9q܀C"X s".@zVnY楺lf sKkn0oHw'qHjmj46]qGN]uˁ&ǟ)k;E']zLSԒM}/yk^Ai#wX^dzo]|NYd=YkE*e1S_x|/-96q7:_576SEv9=kiÀZ%Y2 ߥR6됃<Afq4Jǖ#-.c5OL}%B^#4ZU{r3NbM|5}O~ҹcjs=^7}\ݫMluqcƵǧ~q`zGLSG5tPcOZ,譿q'2Ǩ};79AckzQ*[ 絠S5r +ǘ}UN gVkZ I 5LUT4bK`1ʱZSW7.}-ڷR'kѩn0u]ս#\mv3߭qbʡ@NLg'^֩5[U65Sg뤨ĵAK ׷<]ue)0:fs}v3~[}^;ȶ~'3zoӱgi UxGLt0Gȧs/6Ǟ制 ;}/ſm?@gګm'[y׮x'/Dwm~8?W?[vr&js m۸FEy:L$8ZU8OP JGI.2;NYڑ (:H\!p>xϴSAR6(k%DzA{OeVh4EHETo@Ӯ@1דVjYXt5Xf!Î'PKjk;Gk-1`y_~l\P{Qi++{*57\Gkl)*~os'yƧN-w"$'_BkrBVnTQbƚҸ[QGmq\r wzиk"HLzJc Ge T]xϤI;Vd(V6ϹmY-UHIV5%KҲaXip+M77̐D3S~; rn\qa˜wZ]1\p8,4ڃQ]`8'k, fH=AW䏬+v|r-H&}'ևWi\ ZX4?P-~ETrӕ$:ukǔaf51GSi.(%A9y7YV ``bGjs0.u aD秗tvIMv ʈI$k\*P-01f\vssXH;ElRa{8yD+eBb w+Xva2+;V[+0#jc^AVZCӾ~q0ZL5I|1D*p}&S@Ep;h`x2:jM̥h"vI($3ר-lg<"n<n'jgz>jPm;AO$R"W_3TZVJOڎk/*+*ԏ-djFm;FO3WǗvDjQPOI:ڧ3nĬ'80ׂDQCQ=iG0~Ʊ 1Į" ̂~s]Cx_UǏeV)^;mApןDOoH kr?4=7oimwsI\Iaj-ls]%p}mb;)ڻ~%%I 8{Gmy|+柨 z9o7^ՄQ9-qHx+|HԱ '(c<Od&8պjk%.m>E4ǙMem`)<ǵyS[^pdX"V d{VqGjj^$޳O@k(\ ޜ3rJU?jœ܀l~CyP霳~ռuG_,b83ҿ|O7j0D_ Wv`ۃcsYyB3.`F?5+K%x n #<.ğbq~5,$u03޸X+hMR?5MQ 3"!@DIӐ=OJx[w!LG='NMc*#oY{j5Jg1uʮ\$I]{Դ:`Vpy*%C]m<[QHRk#kWZ$̈OlҾwȺ;JcO|Y^ zcS'xq:O ռTuJ =a ONXҲ@`ăT.qBW/;tQ7ԯ= TMuQ5X[Y`,s0"pO4I Ro- 2jҥvqUU.́@耐LjA$z!u [*B DVr`ZCGCk`FaU!Xdk'ITg`"h &j`p3lGhmևdLıeG j`y#wvL}>YrĘA*e@'5K6Iu,Mzg_+_RƗR֜.0A 9},A,I2O?5sN|Xa#WIֻN}#!ڨg}ZoN["+w+cc2Ƭj4I+ڸug,[ ^k'ʱNN~?5*_W{TP U><_ԋ r V#T3otW HUsK\sn|<&LWYc֕1#s@;VꭅHj4W֩oj%SV=|E-ޟ~(,l fzP M<-3YF?iX(A¡O2N`B ]9/˧MXԸ Fgz:?.T9'eO$TjW:>DPEz F e4Jh砬I 30Gj* T+DH'Ύ;D{aGz[A1>k#ʵ*֢F5feZgp95#3Ԯ h*0}S]bjTCϵg_·Y^$`ȩX?=Ye];[,Q__Wߴ}_? ~bF܏Wz^ꬫF@\]7:7+ޡQ?Sx沆ɂɬ<]-n'WH<_ۂǿW~+ۙ ?k+ӚXUy=*YXsēIn,xf\GSf؜{u;5u O"3b^rđWzXz^V>ښCrrXTĎzڐ 5[jwSҚbkg;h+9t,!p?c]rlM#'7ȷЗc^^_L{<^-?w[ql7<^ڻuG_/kmz+8_:p?>%y鐕\~zSTޮ&#|kg?z;m?Gκѳcn t"ńX f"A3Ϊ$O"=5Q'5m vl' U`h۶Ix}E~'onr#޾;rWi'W0͒#VA%Yr'߭h-E2?zXȣ=tuA+,ܰD}q#Lv>:c{☝Qj~Fa̒x5R1j̞ J${N:ȣdX+5^HZ)*T hgM`RU( l 3bú+ۓU3k[S,Z &d|u\Uʜ("2+RkIlA,5  文Mn"V0g^PB$;rkT{LL>k4;MHMqEUd kHn~)K`OZf, ( fm&*AhgwA:\x`9?I)/'۴H)SZ_ j6TfgE^n(0ѳDŽ @HDU2Z`9 ]u]Ӷ7[.:]{:qv?޽SCJnm ?5ӟGx6ZЕ 3zcmZO\ bkkQVde[=]ua5a >YjqRLH?ctMR,Iڷ+h g}|{J{an>7?=Jh\u5GxlӪ)μ1OJZi ^R W zoˉfA+5kG1wXvźu43Yc/Moi^V3+z4Wr! w6O31&\8H?^AVZE5ήAnjT09=STb2[*cUG.W ֺǛ.-0 M\yzZtRd ~ki[bJ$[zWAfMڹWS;2gEqWHQ#L꩚ѷy@4"ÓuW~9Ex6&CF]G@w{Q }2dsPk|oN.ԕi*A< >夶B/h ~onk|9 s#|n6‚@_KEB&zW:>Ӗ=^M53tzV :y}[D%;r@[%R aTJc-T8MSξeM3PCx~#"q_MtHL3$ve?"x 4t:[kدE!=YAzVU6<'[r%px5ǮgsyYf_h9ͻHO"+s'Ǜ~R=:#TNsk񏦷y\}>f8kKxvǧ_qrdJs^zKL[z#еUB$fg_ V} |ς.-W8Q|,=S'gkҾTJI5|kwf U Fz{m%tYjڍ)r>5ͪ|7BrjUn9j*1x 6MXp>G.qZ>線絺?-[z"8Z6Jzv,ץ-} |Ws%O}N #zsst~5j I;Ʀ&+\ֶW2'VZ\@X׫)vEDhĘ4CѼ?{띌񀒼μg㡼ks})2I+gd_ oSw Os_'[.Ps^އSp Z7[kYp'3['ƾsxu kM7wDcڥqAwEtGF3gB!Q;<~;S}Zy׻4B$c=gt@Bǃ艶$:5tWԇKwa@֌ *O?cw\7[[; }3xi{UQ{RHBO4OKiˍ GU79sk*Y sU^O6dw'R\.d=TYVC8nBSK$k\edOz]djK9"FJYy5ʺ׵DY{hAW=tۺ̅\Z TN݃r>:J=>b1SU#FՕlE&̞1[,MtCܤ}#?zx\<+ڱ{'_s8ۡV#WjC5X3ڲ tĩBխ*T{mA'S |EFx LPXCG>lڈX[d!SVnQI5M--G.߫% [$,NTq43go1Vb/bgr׫ 㡫[;T܆8IDJ4D2M ?0h/FWvjmhrv92~kRGz4n,[XqM0O:%SD`(H H Z>X&^bE>'MmxGbųqph "zq1bƉj9:o Uu;y&HtH\8늕&4JywGjRjhanovUwyP$NfwpmɶٮxݠNz<n}8v Wy-Ǧrl<yl%@R6k `U57,Gڇ`Gj;ӨL#tpiv#f ]> PD`WD 7S5@y+DU[@2{+aP-ؠo{OJضHY6 4{n,vc5c)fm0@D{mv- =0+|?ӋuBs~WBŔN`N=@5#Ŷܖ%v{*vHqԠ dDXʒ]zрjmAU 9j-_Q:G!.uTA'OSk%]rskGNL6[P"O^@ GO3lZҠPct{ JKޓǁX[L#-fKlN$٩"ӿ^;sMQG><}zxYBnI#zz+&عz^+zPw(Sy=~+d2ͺ Z[7 ӏjE)D3+c;̉kx5mg<~tc_ǵ|%]kT!v\/UJb e" Ml헇9~m-n 3G*l7K~+ϓ:}_ٷ]GmEpb8{#ѥQ:|+ջֵnJd{?Ooz{6r HaNsqֹuGCM = g}: 5v_}xUb>+˔̣z'/:HvLחd(kukv\@ g߹+;SyO]*-gKY'*LqRc}=Tya/#r?kL[@yyQsb$t;5 tɢ b4 \Ȋ^fxU$ڂVlAg-4G=jC(Ϲ'lD (p78Ge^ bE5ëI@;AR'zX34s6=[[ǹ~xM?5ۣ9nNO9k22zf}ұ3bk,ئ#|X'^*-Z%jBGj,hU>IJښM 6F`=*t\Cx$+Oqޢ,\yL0: []gX@xΣՁ%F:z}X4WPd׽y,zQ,-Qƥ)NWs<55nbK\?,+*Hvxܱ`?yʉexx};+íV?t^0[sOע}38ڀ4O3]qwxzox#1:Oa^n=zߨq]+cf} ~*5x ЬIy)w~w.LIMf2kƹ@`zqRm+&i̧ոc< ~ߘ&|Ա"2Dt÷o^ q̘f;M'%3}*7#Kgk5>wd wHc7^Oq8Uzi!ɒGZB 9`H(%v+dۿ&2-S(yd*Z0jD˖ns׿zоdFmG2r}|⛯O=;p<9vf$־|Nq_%/߷YM uwMu.'P-ָ$ɫ,/_bҤtWF60 #UG i$?*8_~}*C!A8=juQ?Ke[LI NGaZok 3#+SZ:_]'<8=NSI%5GNl.a@ξKDuO=%M|jn5Jc~cy/w&9_(uxAῚ{a"L<5^W]tc j4lRaXclD}M5&Â15Rx2)0'U]ң73?5q8xm F6C![+X^7T,OSG]c1uwb ݵ|7Ë{A\ta~*GS0 cMkrjY;)c,v?j<@@Ǫ4nOЍEsFH唆݁Jz4Jχ78POIf=ˬPy<_XrA< KJv:3TֶAX': ),R"PjZb &pfAb W ]cKMh)dWX҈55-YV<|W ]`**&Ҹ OQREe*}T,yPYD^ ZӠm٩TiѴhձ(ܶn3W\OǓ򯩜p6}_+UɮiZ 1YdITXf4H0jkTnH #j`{1+GahoO4 @hӕ-54$Fnݫg+3[p֭~k]"0m䩚=:lUI(!僐44,PYK^4iH3ڐpIW*`xUd3$3e̎5(gdMڋ,dvd` {eݙ$z+m)Ql|΃uTV5bޔ$LJufښ'kKlzA5:Xbc0[dcFޔ 3Tb阕p f64Oji[6zub \@[|$yU~9;JUGrvYN2J5ֶĉhIᶅ փV嘲z8m.܆ey+>]U. &"֯RN"YYzI9oӇ UA&H\: wN@%Wҕ|aоm .L NzKQ\E!%dϰ,`C|‡zk@~k\zJE OֺGJtݐ;XZ{ 5^ {UG:Ak\ޠ+ꅻ0hN(/>t Ǯ*fLt(sHOl,/M4K"ϽhUCҹ9ߨ\;@_Y_XRk '/6m_In!LR=#[l^L h $eVU!IF'wT*_X>H7&望n SyJ$#i7H& ަH^bS{ԻAQfǯUE ?ҳU + aXՄ[w: b"_7@PDEEP[ہ z [CQ ,z:kVZKARg1d^O'ɏ>֏-^y廈tks-p"<=@g"Nۘ5?QO#q]#e㶎`ɓtC̜ uMZ -$`SuZr–W\ WӋ7H0 E25afU@l @缩딭h_B6dW]嘽 W>WڟdpN;Wx<ŭCA=`ܚ<ƼIZ_0A3qz*+"o¯׬: Yj*6&p(x>5;ۺ f+yum2*68+64.N~,e˨ щAP\yjCet1ZpܙWܽzQΆ@r]Rt;\5q|R8W37ټWv=<2s&9T@79(^ծ4M,GhY IW8 %g98j2I[IᜓAB$dp8p ފ,IҁD(@ G^#,SkގkBѶ#lBJ%ge`Wnl8=nڰ^KsRYKA 7@JX(GXs7dy6|pd[]7lD˃#P"9b$MMh 5vqXN¬="k_JmRRrtvNmnJ ϴ׏h4@\ dxs򱺾u}[ɝ sL:Wtmb@jW/P -Tb^'j*+o(Xp5+ƷiRMz'NV9W2 vEPI׵VHC鞼Pw~ҴDv:; y` >6::W^]3=­e 9Sm" d7`D-ٲ}FxG}k>%M|Z[,۲FO?/[mY}Dw:u|~bkc]IaL]ݱ3$qMW>B- i~ GjE p(JDqV?{UDҰ5NVX+qmr"[kNVGXU(Cv` BJeOZI+˽;-`r~kt~ ` tHgk|o׊p汵n0Aoǖl|І۾F&3^n ,L ZSh>ɭ: Vz@8jLvSb"n޸dހm.C1 =?ª<b DTbI@3AO;8Dc *F֎9-mEAҷ+{J퓻}K_N_'|?oÎK⫧bWLG/>+e-3>5oYט}OHkAE{<\qvh}*%9@وb樴rIV}S 1 ڰE[\'[yrgN2 JoM3U֛+Y**,?jN:/ ٷ,tKi$Hi\&\m7Ccym]C\u5cٹV U"XRATtnD; ]"vNLzjc{ȯ?U4tHb0+Af+ӕl]$Ja~ ES$Bf lI=*"Ŷ.T CW" MlkA9MVDnEls`jc+M{/'V1='|~>WNWpuLֺljon6:sYա7@X#3_N7A$8%ch LMn kbJH&> FHY\NFңVY@jT\VPf9ua>jE.s1]\5ѰGv@wpm]yMPdJgmz_e,/N܊']x[4DE g=Fjyҥ+A^O7*ꪽE9@R۠\<z%yΤIb(Z%۪]T+ZZ{/O@OںGd;vT~ƺLJ͍b6rjۄ' ctB΂{>hlh;@y@{QŸ5ŔVp ~. DuU h2chbLǵf $|bűOkG@nH8 1 ec3tv2{L <:gz.b9+0}ݹmogU=.B9<)nKJQ5y[WwS'L9(w,ǵjud|<~:s)V8%Oj_Gn6޼.</[^b[2I2UsMJHEr@hVA- Ph@֊-ēyTgoPh%A\O&pjS_L `['q {W+JxYBA'\,uoiWNqwְޯ:r|Lo]?Av#N[D+<O]}.Jq?DeƎ Rk dHD-81eWB+\>@my8jծcs3G*OX(;G `2 ߈zR}>©pwN`Bbŀ?T hC$jfq#^/th h D2E~Nv&]T{DQWApFs&4%DOtǖHVjjւ'`Xֆ 'NaSFƗ@T zTۆf aUry>:,ܲ0 P ]kK1qTk;V/,Yp n']DŽ}"n#["kP 7Vp2HQ鎲a|1ZA}t7xXjX?J1:WЀzh1SD@LsZ lP#s\ϗxGSa"q^^{~Og>*n:9\v:]h[As=hL?.]ս}^xM@eXӂsN: :UDk-uO?(E;zgLqkmjINE-8'+bj]c꤀9sA5k4*xPwdO捐AWI=1E gm$`T*턖?-fϡo}RݥA^RުJzA޳՞yZ be d{T_;#b5Qp|O߳?2F9xӵE]RjLrY+]xϮ'`|>ޢeO~rэ?^My1uV}SoGa$܊x>5W.y}CwŮI@Iw< eVmı=Mk g5B,[`=۰DzDQ@!Ĉn 9;3QqXH?ߵfxA1뾘vHk}km_En핶@[s殱 4RnaqBX:h':=zLnj}۠ @m @Jݖ)oPj*5X+(^(Fd?\y|7[@mx'X{Zu1&9bk@n`,Yx*i%vƻE^H5w ׊; ?X8FGkt;EERIcH-RbUG3;COcVPsPn\TsSFQro*x",&9~'x\/7!y@!g^ ygYtuVwwoՋ4%IfA+ֳ j-ҳ M0f;Z$*Thn [8j4Ŗ Ե4vCbf)|^ I#*[ Zoj,9~r2.\99js1#:s]12 oz: x j^V1@ `?g#޶qq1XKj*GkkTAު }E.=%er^5 I_WǓ|Hu-cHvc)wCZuwHP+@1eFlVo\c\Szx} ^]ddzw 0ubGQ7XiFc:`?8&E#_w, G\Ժ0t_ԐT6Gw]slw~A<}?]zO6p@=q\(݅Ty 'x9wOb椼B!GO_BG|ʳݸm6-&q~c5G]ȱG^"5ȷPGWzQeB}:;z[JGx>Kt?50\j7 o/MYB(]#^ҩ6.dG6+yxbߣ* ,bkLjCPshj\D*{koRۄ^{V軦vRHhR%aJ ZbĈ*t.5 ,tLRiwn׏rⷉXq$Dgwezdkt껥=]%Ӽ}#j$lWP#p{~lm1%s(nlcT.8u>MP^:}c>;v\bfD@jk?1Dq"V[^z.D 9*fF&ԴE;?j. 8,0jj1xJٚ҉-jkq4 f{HUßOShYK&G"W?K}WjpZ6I0}5i~ d#\{Er|\4s_'~:enf`0\8:+uocSaGf1+s~!ۭXpKPڡѷ>9~ѽ3޹u]c| E4F W94^&cnk#^%z'?{T-yV?Ѹ0$]5XN8ު MòV1xXd?Pcc`6yѡ nN}1(ynQIUk^oÁx*?A>ߔܣj~бS5潸>:[m~HI5QUɴFIwqY] GHE:#5lԁ d+_h1Z@F9f} {(#c_jR|S]0ڹ;`0* wOm-'q%p靳$"[70tNgڎ:Գ)۸Nc?>ER}G%"@G:ѳH2OZq@ Zӄ-Hتyz&Nq< rV04s‰sыVlm'iUˣNj1d(8J9`4Ae+q' B@]q[ NvISϧ4|й `;(;byہWOkFڸ@=<Y}% z'F~^||],K5kIlgnW?m[:5! ($x/wQz9xؙz/']QA׺_g([tnm 1D"nA T$H޲,Mhm = K^j2l pVX@.;X~kkA`'lVk&Hd d4gǧG75oB6¡efxΗͶʧSϼ_E_3uz_qomdmh:/nņGcSV2m'U(j!+Ǹ?5gVPIf->%円,8 x֤59PsAEު"ps0; ?M Ď+|$wUƥ\+nxhdDן74Pّ\+Ri#]$qڹ"nK8PҦ/#xI"B?zʨiYT`r@ѣ1?j68Qb!d{ۚ"+mbAOWGߨ5 n;j\W^qڻ*5I?4Jd?58$/4~ոOp⥣[hعR.\+ŎOMn nm+N01FiP z ]A d4|Z3U#-gA7zvIJ *?sTh[2['[5][;M*G_&9XXyLjkI*Ѽpb{i 9'D|pNz|S@΋XoDbP-0AhmCDGVh-(Y䎄Vj˝=1X%jdN%Wή95'R2 1M 13h!b?,zRF=Z0pc(Ž:wE pSS/$M1n 5"->np8S4K;Ɏ [ h=1: ܭK<[^'cܟ XIڽUʳMfT;jI}rd 5&{nczxXoE;9tf]8&S\Կ$i{VdmQgލ~ U0##hmK϶0\z'Yey=x瑬^d׃1O}Wg3ss"r`'3P+ Et"##{9w.=,I:o:cA{ןsxpn:xO/C\Xr}ٚW>#RoQ_1,f.DDGz_W;6#8ElwZ=+*fbaVSrWuv'5<>O4[l G5 Mzx5Xē]x-U: q!~Ef_voC@5q:ƬC]~Ecު*Qmw7VbGN~*n%Z2@@55km.z{>1_ʶ  ϙ@YaD ,TߓGczJG F4BZM;][*9n[$yæ'!'iNNsTXڒ)-Y,:ws\iVn0MYT)ncFwLl{wtL$Q]Pr 9P9>{Om0I/mx톂X,d1U:}/m=q ~+yms?ŭ^Ƽ)|q~*M.^G[;PgdN+ǫͯu(Q?j~ ˾|$O~˿*[^i$|nNxP|_q^臈oИO=[Lڽ{6-}<|׫xHe /MHn6t.pLd_ {v'GW_\JOi⼽Z$F;k["Cp@&1xa. ,0*ucξZUsi35H1tmC-?'ޭڍ©>I9pn2`XZ@eu8n ,A'15/Oژw*q{ҳO- hq:"pnIh"H<Gk$T9Պ߫(zʅޤsw$Ժ0uf\d=;qζtIkֿiyMsrޡ3^?=OUkgE54u<[T>F1~:|դob?@t¹+v":kVtwJ[eW!)79ӅUPA }Uq>v,^HK:W>ςdjfc*^ kO)} PVu{q31F)]t 庞r8^>[[vĐ3'WY{tZv}ʢ Eu֎Op8-=%|i . AW5Ogdh]$z:`-"kq$OZbiY 9'XذY7CՖP .=?5QmUn $+`QV#jV~ ׮u;GCN#H8u2ҁmV2`I#P4 lLMd]c\[XW5x^E 'ڼOh&/1 dtZ11`Q1ӿY,HSm{:K:W3YQWF (q~5(f=IY/?PoiyeK^jl'qޚRddLfdmm`@1\t{M+6tcp4\kJ?"Whҳ{cn?WD8p='#sҷl+@YU:#R塹j7DFֲ ~HVūw0!:X݄UȅV3&ILhKğkcykyK~ھ/rx&ḵ 7sTଃ[=&?Q)EBK6i> m۸MMBmX8R7'(j5FzU'7p*nŐET\d?\ހ`j*yީ<*OQ[Xj 4@ un 9CNTf+SGg!o5K& _ސ'}g8PDpDsA+n'($nDB ?L@{&mQ|f9&p@( $bē@}>ǵkdIPz̿l1_d N6߁Jچ#E1ҁ4 l;Sm p$DF,hvF5M K8Kp1YMQKVȝ\8wZGNǔ9}9yzq>!'vrCl]jːID=}X9`Z W׭yV}|'U`L/zA~\>?e}HmLW?3}"|]Y k~Xk`0cp۸`})ur'5!}'{ĸTcӼ%# |UV{k}oX~&ŘW?>zsw_v3tτ+rBns"Gݗ[Txli杊]c 5TA3WHnyFTI]e Z,]H2+bF3\V l>֌lz1&ڗU%=Y@P:z3Lȸ1VQ T@}ENkJ.0 JlH+a0zVkǴ'f _lY,X|oƺq^{qS,G?$V4ےFH%[Zػr#"tzp0V&u,l0pj54I Aj]#5*֎ΣH*"npXcj(eY34CzA X5a9Pb|IY]"@MKVZXE+:Ye(>~D|wk},%ݡ rW_ v;vn@Yדexϖ&A3Iת-\[P̌dS5l;}gw$jx$u\z- ^>z9@'|&HA$pD]տՇpWZ>Z3uSj1'"j@uTyrCwTucI/n{Mtz4ͧLh>.$,j>it]h1PF/tzڊvT|r*\p#']P7;U<yyRq֡ŜϾg~Z筽.͠Xuy'˪o-W q[y۾ $ީ$(=zVY.ѿq-*ÊHٳ a=ket`9$|3m7@ǽ#Pʪ21G*vDLY<1h\=[d1*?x+ޚjJbnEiiy?TsڴJ O4m6d5KM6[JMJ:]Ahec1QPӹLԥvM,[i1k5 v̩TE [fﴚ%Eϸ"-F g`g?ckOьT|!A L}ܫ꟡> B'޺H^?KٷosTO,Y*VWTE kz_OSu}}${$W{5.ׄ:VuBd+qD BbI= Rvq}]`#~s_ɏԋPTL~k4&Ȯ~Ԣԁowz>k_[ppǷSuT58Um?B⼂G%Si)wbݧ/49זnjm>-zvH\{PccSV\jJ sYZ>\oQ~v^ʚ/ ]MN5ˤdοhϿqW,etO1]#2=f 95Q&P8 R#y#vEV0A\mu 9*_ɑ\k[x]uϤʭg '+n,YMMSOMaJұQd"-vjŃ GsELPRcl ?4[!;աhXP {E\K?Wn'ۏU_UlU}NfFky/7H 1py5n,CN$DOe,~}|TzD_Ǡ|IϸFtO[XSjo-By~C_|Fa|j,+ >g&mJ] sާSI#]btv{pv}=6jg :h=VR外^;|~ώJ?vg޼2mL=yt> aJui[ ̈M^:6 ا31> mmefٵr~U}6Y4kPl8բ`D*l-8w8B{%L k3+d`DVbR#hgx: @c<FKk$fg⼟#\8v\pD3?ڿ-{9vXA* 1׽x1^}5f=ؐ1Yg^@fs?xu\I#ڡo[dy/kZTu,^F"Jn3jkdCA=Dn[[*F j+^/ Q]_)Xdj]x@dT00=h_Y;ϵu8H5<cuonU+O.=@Bcޤ|XԵ6g w(;$={Տ~(˗TG'$ :!I`kz9nl5x?5O.Cem`E[îT*޳c_ 1qYL\^{k#R #3g(Q*vKQåmVF' sU?Uk^eªAsr K{Kos۷+ǼAŸ glqYLvO?J l: `_]ꋑGy, u?jL]:!h294V2c#Ms!SҝȺIiq!e$4dtB ~hS0A4bq;|QZ3=G78  gi=L]^H ӡ@}BnfgRPZ:4nd2Gfvޠv eeli@js'y\qV{`*PТYTj(,J$A;8UR2Lf `Dez_TY{f9W/ #Ke_Tt\u?O-^0`{W^\Uw<#00#4'Zw^x D0$E,/d_^ݖ-qN'E}Zۤ{l^ͫj }'6>j-F9~kp*}EMin cPA"{k}N=JI\9[Vi"t6@#:K{?lԋbۣ/>+SD9XF\nCPglF*ܰn |<ܜTbW|?LsU*qG H'=*4zCdГjC6phPUy &W3G [(ş0Y*H`GzPQ 13޹E>~jj}=Sx{KI<> rlC>JߒJbޯ_T&e۶!wv~ߤ ;\ZoA R:sYxHkpF OlOSEXb>Ŷ󚠁VkBVdsFTI9ډK( <:$gUB2kDT'{`X i+,ZխAurlYpqCOj/sZ[ y4'($fa ށF$.1@2(ډ; jM5,Ń ڂYu*u嶑 PZDZ=W|&=t\Uܺh@3@D[9-t.qYu{_DIg-<@5êc[c0zܸ8f uε>|B?3XCY۠zs#?zm0؍{_GWE̞+邷t!5^ݱUMeϜD3l`:tm tp3\ιﯼnxuɷ `󚊘gۢ:w}AQjW`U187uǚ/LSWI݉~k,9y]Va2)`hyݗjL+[I 'vD|W+6<[jcuC[?x{hZ"p#¾(M֚RJ9+;{GIw=;LV}PzIllks'*>YfWyk*̊ 2#>Wr N?w+ g3IuW#N* q|@E@&Wxվʞ6hRqSs\aFy\u睰D{_Oֿ9W7?ÆK28sھ|n/ OuJ\W2y:HhZ2:* jJ(Mk M[`)I4e,`sT#[[ Pjh ~;/yWA-g= zxX$Tmo4ijJ( ăڷ_Dkw__*\S6~lqU|5S>M^]pns֣sX#$5.n ['VM=b 4\R$AY*%v>k1C@΂4wśVA=L`z0$kTDј9S~üGz1V1Rpc1[gk<08;gޯ8kڋ\}r2Vu-ڌ P62!-'PF4m $DZ4 ֗n VdQh@-D9PpEѕe?O0y:TbH}|n[[\$ErOesQt$z띍y.ڄ ֋:]*TM-8\msV.3rjZ`ޙ#_[\J5j:{*MPcڰEsXkJ~-鉸zT. tۓڢHrћr\t\_,NW# ĉȨT+*`-sull ȨiH=:TU44IT*m ɐ"p{si3F9Iq[ v& C5X~ճI(y+ժ$LҾ}>gw>!y Nzkю:L֚i 02 g)< 4c~lO.'HkZ`z`U&z`Ճi;=<ǵV1_tɊ=`f$ ֤6xj INL"hCJ4CML ",(@B fT;#l$;\RFOj ~IZ,@ vpw!yA$jߑeolc.u>_>~?`߶ \_W2?|/еNۂWg~+G;BQwRkb߷cj|_m:%mxcW+xa;C@LԏRl>ƳOoi?^+Ӽ;$ggL;h|֫k.f1"O#i-0815Mualxe۽\jZkpA;O\Mx@A0#Z(82:հs;wA~jCMV3tж$5n+)VAn:Ekq p85442HKk zbmo5jBg?5 \$m) \⧯JF k_s_,W;p'H 91:W+ZWDwPBk ~/YUGL[ž| G^7 h$4\-(`.UUTX :ˆfZBq%y[1KqukWZ+"tRַN2sm]ˠuh5RN3j:z:XAP`>gNmzIZ/'T-f󝡜6A\EZ$ZԽͤ<y9U264)E Q-Y=r|)ƏlTt[f j.U\WP&/_,vCH6lnEnZ sUsz7o@35>A~*QmVQ^=x_\p{ոkEZmpF @FhӺZR#qJwW ;HU:2dW+}O2Eno{ wToU+t}*!7pRI$?z__zkwm(D{$G㞕~ _$} ׈Ziջr'jZ篙uZ' 5]@dr X#]NAZ.Ml=Z+9V$ɠt9={[郔r`*9LsSMwKzc= w>Hpje!n_0F$Nkv9E-ꮲX#\v'n6EtQd\Gک4KI&GC[ˌhLJ|]pDA_h&y n޳`Rʱ`ԭ+NQH5; p>)/ I'=+iC)kv*W{g꥿mCU "_YTV! h<]ۚI'yUA%/zqR2R: aOjqSD߭E}1c Hur54.r+k,[V'wv15"3TWF9XkpqUƖ}I9\z+[B]#bսp kLjV*&ﱢwO[¨/p njX~5GJfuqR.&AwWr~^ml}9.F\XG5S5b#nj?w߸@~~K ѺhiO?5D PCc޵A2jҜ3P¡-}TPYVD}q޲R}~S0#" T"[a+2{h$$d46@lxڂŰcmSӱ- $v4>Cz4*vTRP/ qbbE8 $hū)mPk멣w‰T> mڴē#+r\(Knd 9zy33\+5y=з%`Q_%ſiq1j!a F'moFpk ]3>7 L3^L ss 8lv~Vk=8*ctz;[z&(i+nXB]ݸӸ ra] EZK3sT&70}(l ւ89?PI-c&gs>{PIndPI `v:ܒ2zVKM*YFG燺!<őYF<|ϙ7ro=i?lupCg|B6=FȯRpa?ڶAZߧ`9:bONF~&-Wư]F c=k+_PK F ytݱm@$Ѻ1!(׽R񺊆{`1$~tm-{Iym(:5x{itlBH s;e_wh`YI~d'[7d9㕝5XX=~oLcʵI:X]?m84z#uܥۣFOYze:愬K:KY4fL$(Tە&3"8չvdhPaIZ-m  Z</$z%U z뼍 6VTT$D=N;]7%]*XbVP;w>ՊKMkGHGolߠ/|<;&U*HhH2+͏\Ӂg+60h"l nU5*\eR<̃GiQ[HGc֌3|ϓ"վ}i*H?N)~SkإvRLިe㈪0]"k["v[T=nZ5uGNpt>q :&,]AOjK !AQVQi#scnI``Pp oQP+MV6 D"LIWsgSZ> X8;G Hv@A~7,=A`)*Yk+`V1Ңg֛w,XkdfݒGɨU܍{ԭBp:lGҠ1WSWߦkci7cjciHf`0krunzcoZhF]%EԖ;G^UزyUk155Ox5@wXpG{AfN &(C+欰沈={|PTX%dqQbzfOv*WomGQ֧w]nlŸ{3xm (kS8 9yrםnt/}fG;~7Z({p+xry篠;etM]G>~GWݶwÒD ƾnyMzLAC]ѴvͫNp8z#QoX@{m׃~-U1H9B-UkO>[ueA Z_*]E7~T3y}@t #r-#ܽAvj++jh=mzGZw 29sd}s(%Ky h9μǚWCt(:*:lVI60p ?@nAIT+k1߷} >:}==(In\D{o[eTn6{O?D61 Oڶ}Aຍ0{e:2>Ea tUzxxMeS5 }m]a1v[thb=W:/atȬZxUzor)$ #W;C:j`SybC7t5NSX4ɴ v>GyʾsNq%#s?;^c:4bKH#/Q}1T{͹b:z7 (*VH=k~k688jXK) c.ۺjm19kc1I 9q.[n;F=G|U޹I[qTtCf`2 j;W7,9lQѣLq er~1K?Xa[c֖\H6(܂:tf/'9#&cq []Vo]@ c8X}GJ$M:>dR;z|/BO,dR.Ae]pЎհwŶhYSwroETHywLTZ3VA'ipsDT|+։NK4N2( 6DP>̜ceT0--?t'G{u\U=q@KDrj A}G7&b(? fA\. 'M? RseR 973l?:+ 6R5WpsD;<.޶́|[Ꮐ6ѷN6>ߚY܀(*ν0E+bY+^5 S5< C<9[Hnz^􇄐@b5J1Scu?l ?Sl.m k|W}cgr$9k5i!ՏwJEf6=PLɮ=ǣW ׊1H_BPzU-FpIXFys-Ss_#7m9xg/zumrSh[ ` fc_fݒ 5Ϋ]sSqI1*Tn70Gj)&V"=M0rh3Ո5<}@avhFԇW-$Oށ,@SNX, $g."^ՕX~*Ʀ^E'i*EW"B6 vEMlͰ3 5tdVVƀ`|V( c 'ߎ!ktU,djmkwUc2K WIQ`%F]5[ T`d={F"&2~;Q4DsF H(^ep=`!Č#h$Wd5B6$0Q֖Y.6 ˛䬒3SNUۻAwR;PC(\fsRםMf3XE$}JYQT$sU4d\]?]pJ>kt64X+i6E+Zhn3P7G ,6n?앸`=@SGN*9'Ւ;:QnʘͫI@71C^3ޥ6_y$Œ>mt⭖QNhzWGWErh}ؘ'̵^5ppZq^\X] jVJ1+ yj*2=逫tp >x fcވgTaɌsZA5<19I($ b4n1PID#zt1EE ȓF~(.EV'# J( hAm="AW$rkAwbNAЗa) gs! +`iII l}:VcpG 9f'4B0@u`F9L?WT`[$>ڄ0( mc'b~fX350`Xȿ;r{Э4f;o$]W 8ׅeI_kGSک8b aBOzx\;y>2,D">yH/ꕞ`u4BCbGc%#cn+^tNX~kr_t] WW/Sw<ps։顠m ޥN-b@1yUv$4S#aUJWXo7LDGrP TWKda&}ݎkUx[Lf+x97eSp3_Vsג}Qibgu{Upj611"6yml*yf%G  m }\yWPz^ߏ3it䒠E+No0yV-xŘ 1xRGH$RVyuu2}"FۖAreyXp= t{{֪1s ,)ZW,ڡ< Zo=f.(@?kb3PwذpOބ]}Lު4A`T I!#d\5(\?ts.zu5\Wl3 Sڿ;_OG4qxp ξv&@7/bh)j 'UUkH&+~ Ihxɜtq$  Hb}P`\HaҎԧ 2WۭdGY]"֝ch#KjhTb++kiuN?zר}_U$`Lb˫cmJ|TW OW-IZGĐu!sL%Q-x\_>Tbcduncҫ-?tK˞GcLZp8BWMw#$Užao{`.ٌH>خn+buJ3e)c$@5/GkOD_ZUI횾^o+ 늗C)#{UEȽrhF:kPH\Էt'3&=\aŁn-kx~ Z-hmh`Eݷ&xjb}>^>se0=h]6Te&AaGNcѼ*ʄ(qGt]?U) f8IRy}:s70TQ^⬃9yan&\0\xs`pcIq4N#4lަ"}*MDTַGU ցّx{kcjpO,+t-ZHf]Um\#Rȯ`@.9VTֆ$b@Sګp O?3P]_UdrtZ7,-29u5ŭ!9E5_ihxʮ$_U AW?f &>(6mjCmVNI?gW^Y۳BPH^f^o@p&сwdAՊw<% O?PbLgNQyjfHmi'1hP bzTM][l.DgVKļp1kjPPlF6TH'RuU'ފbA@$'d$1$aOSҁcԬ`O"!YAHҀ @dEJv + jG2c(cX `:fMe\OM[iZh\fڳG3 wuj7QC.'ĈzDP-9*XT<"р'ީ:Acglmg$5LN;V TIɠkwK75С#X/Cy"IAm#Ǧ*GiYnդڠ/?l۞"j\Pr8WǛ3^P|*jopqX{К+E`qlc&5灓Z/ U'nY_bGv~01T#:!}ڣu\w5P UG>jk(yvJ6ҢgV>KkܖyFksqY_iW^~Y]-i40g޽oOtK^БGVŀ֪3YzE>޶ n{?Odt]T^HLKw*kFzcxgcJ5DPW&K&'$W*x? ?jXd]#` +-=w?TUTM`uI~ \.:~aA(zs*9zVrԽR Z>hE=MڄrLP :yJ?K?tGJ1ֺ| %N表upTRY̊`UUGrsC}ZX &b w±c]^;QfgBTRO=z [dXM[;miQGL*&vInw6qX$f"c cN*h= "ck(IaVVIG\YMKcSJdJW! \AGRǵRjV|ш߳qU7U.eVvIr ۏjsIwAj*,9ʌGJYXҩ"tǤZ&"FbMo["; z%p~M`}=Kf3IRWbBWA8"jq̂:.-GPuA'[᥀Mqn0c: g'9W+UfNm zU:5?ʷV^ k̪"%ꘞ2uadSTN)39[L}-i2`CT:e*zH{eWjs\ibTWE1 H] 7$OZ"^'N{(a A'3*YqnLsW@%W)8klk^n{.IWo[DCbE})ju1^<@kߵ{N3 Htz1`rM\S2p`WP)Uc3U @ȮtO i]H/N/-Զd 5T8\+g kkm8c\-qaשhϚʋȣjw<W\ƾC]#k1g_u'/|o]Ю}zSkJu`,ֲrNąYz ^kVLڼ^i5.jE;+6I1+?ܧnO~?9m'Q@ችT'aUGY]_KaU@u~X<=NݰIHHnm뷽u\ٟ[(ʻ G5L\Zwon;VP?:%;Zrn z'd`*"1O[0@ͰPMlcQDaV@{ 0NMo2!A$Yђp=eH8Rmҍ8_5WP&VSzV jn/G,$0zΪ+tup3~%5ND۫n`?+1(b*]u;:{*^K{&Yw`k%yOK P #T26ظ'~}Lb!P Hp?$ (Xu#YKTiL/ egqluMVS+5 ͻ+ں9k?T58G]3Q]#Ͼdԣ0iʻrO|]"+vyMC!d?di4Lox' 7戡UHQ>zGX#4\9g I1G~&;}ȬdzOsf^8ۍݼRوjmK00Ljkkгc!ee4|7r]HiZ:l~9FgIco ފd1ʃEj-- :?[B Z;oDoQH@==Jm{I>^4MO tȝ`clq+Gm9##{U<}6[c\flz UAy">(PʏcsrhV(XI1Y-++RX@YxPġnB'Ojؤ+׵h{i dPXgn hMONpHS+k ;26[?zmw@~΢K՗-"Ի|uWl˂r~Ʃʾ"]h-wmi' b۸$hλUP*'SK&G5͒4qz⢵x#mHx4)n/Ö)'-vbf}A?{fk➛~8$|J'>'~>SHn2ɑߵ|+1גxLJE[ A珊z-b|YR@K[\8]cE₣=wTWI:}" 'cWHٱCl*Z"eGz/Ee9z}leX6uJr%4C]_]`<]SUF-U\3i5F9`wQk͵VŽ$6 rYTbKdzƏeh 9c[m(O4"[b1X2Ϩf=Ռ4 6FM4MV6+'ڀB9 QSCPۃ7`}r el5bD KdBM9+fZl'sJBsX@ l:=hm!U0ĨO[(t8ڵ8ұXUNG]"ldߴG XbS*skkn6ojvRHհA%q:OAܶEJRkkmh՚(F`N"@ajwܞ6*T&WX棥GMVE#ƺ~#1պQHW ]#jH&keAQT4VS ͢ X(ꭓb+]);fAJ fu,h"rb1Z&[q0؊'M/#z㲕=d*j#I* fTZR@YY&DbMT}ᚠ- ux|5B`cƼ+mBjP/6Ș5붛MOr\`_e< EJ)Nu^\" 5O,J[+~K6x~TF+_eS"kSn]f{~>eY\!G>XӱoРWA˾ֶT &&wD_7O}8־۰1\vHo-㊨֍Neڮ:ڼ,ː'=з7bf*- x5qm1)wOi_@JE8HJH̟alJ-P6&fzUY! \Za bHY+&c҂ѱ4F($;R_'SC'ujّ'޸8U:}/C7vҿa_RV=b`Қ q֥@n6dwnu@=+Uz{z=_wQ 3yOONRHK@/os?ˠ@W:oiV@c>߭CcnՍEh<f0Bg;X^3S^Q{r6-5Z +pk75; ԁںm_?5D`3A$r;[-eǫh z܁`3[E5!evZ?>=I (z{n\28oo1RsV(4+j>Yes&7FKV3=kq[k[*O8}m7#/kk7Jם8 "G=cѡH'v{֣Qe%"cډLDd>ݭʗް'_. # [ J* asH\HOz:lHTނJ@ifHA8 d@yށ׽4D_rFV[1YRw2"uY^w,:W^=m\ , R?P> S}0Ȳ-To>.m b9t*ШQ<(x0y }6W!oRm7*΢2*zׂhH$ 9ѫ|bߙs18+~ӪMB9uzsqt#1 /1_ŏ|O$yWxj2N^,}>?Kh 'LM7-IQ+1q,[6Jm:tV.FXGF:u=85aMe~qW\E|H {E{<^?~WɒzrQ]m sk^WuWmOwצ7n[ ~19qXLn^ݱ޺N^KOBrO }ם-wb8,cWde׷rːsmO5p]9XCե6g}ck|xޖ XkI$!J5PV7>ևYڶ޴@ID9+[@>18V Z !ze#p&fNrEEy'$ R .V1#>ƱKj TrϽ>Ҧ#m$*VmA@Efeld;TӨUkvy֢J8\eHP 82h^`%If1nRA[` qRpɩRvv;rbh?Rc+<汸nMhr)uz5ߎ5OK8 D}p7dv?z}>OÔbĕ w4 0==t1b*)b 8U<5Ȼcp%GUo)YZsjP-}=lmÂ&Oo|aiCFd⪞`'z_{J6ݘ~*=*qFܲ!y#S[nxqU$VeAd @=zS+v@h!c?P6]s(ߴ ȃBZD4m yu2 84nꡤVn=IaBh.9f F44DE?`"@@kH $e6GOzm'q@DH@tf ں@"KVX&HE%jhPh/-ՀAǸQ9ji_憭pXЃ" n*ʹ"v4 ֍ko0Fh ]m4 6,IʍrK?޳Je߱k&.-:PyZ1 (7m+$1k ,ފNAbv(IuM:(%I ~++Sl3XZ,CҎ{/7DEtlb`&aR=f%.`G#Mc}?3ZհRv۴μ?rtBh35۷?пqv 'Nk,jth5VwÂ;U};gW\\"k96յp0=>57 %*[Q"ss:q 8OCD_}BL|΢[ Qk+io/kxޕ: }Q2x<b-R&b5=={Z Idž9]w'5L \wqbnb jze b R%kxV b?cEGk@Z<|HI':? "*kqI2i'x8xObІ{6HRr-*?ӌRRşI9 泧~#}qkz̓Ӛ~[|-2H[hxzvF5=1xHk99O.NjqC 9qX"۞g>˙ϵXv zj>f-R(U &f3[#1Y#jAޜ1[ NO$zm}'h$gv %1>.Xa%?_kr>ݫ\ZQtyH,IcX3Ҷ8 *sץk-m)&@ځTLCɁXHEA-n72k65AEոf(bb"~b@3Y *D '@D 3AwXyG+C''?ʱ};mS`; {ynu𔶶n&:(gԈ Hc#{ذׅ+QZT ji)r;T-nI\i7_&[˫"9EG+Zn5,"~2{!0u6{d($Oy/깯[Pc^x~?.7Of=RƂOzXPGF.Sy2zx,yfӖ/kz6W<}U˸A^>[m? z0 w*Lk<鏦gii,G~z}8/X |Whӫxŗ58߷' wPR ǃC+l1(-O^(o|"Eeh:R&AH(?cڥX,k( ZV֤[dH`)rj*b[@Aj#>(3 en%80uӕN96@9~4{ٙ#NI+n"7jc/[. ]%Eo_(JmI]b, Tsp&Mt - PDvD \U%[I^0&OQځnU8bE4R35QA榮Ql!v⢺J3 < ץytw ɏ&պ cnWGGF5FݻF;T`5U0.w#Jb OhngĊ;)ӟz:Hl;OSEA5+ EIjjHb-_Q=HQ@-zқ'jCdv靮ԩH0}ƾW/>_UcW'>G|l &:s^X%wÈ }5SdVGkE#h8+"O bcs({ ׅ}I ""/eRUݐ=ቾE'vͥTҢ0pOɭ Q].+߯a[~vhma׵xzWyv R RpQ#+U|M7W|svrcU[ eȏUoEqVcS3 `XA DYL{w@H XE(*AsAZ5Xv;^ۇ?Mȇ, Ǭ8;c0~64G=SsEiB7N*S@UBYk<Ө} >ly.zVĬ\,oM"if>հh=T,zp&IUݵ+Ia{hI҂ȰsDyC ̙c(.Zdp ]wTkaZr8R]Ir)x㋂㷠MqcնCwG~I27 ̗ 1@Zui+*bkmlsԭ̾k/EcA˃zG=|cf@Rl@N!I抋6u[]SRh:ȹך:O,5pkj.A:*:NdH{?B>GUnPp=ד=9ǖ kpY|Au[i7_FW*$r'j^ہf HkzyKMu[bCɞ;sZ:3nHa!ޫoIc59t~74k8v7OQYtcS:ж6ێL}ϯ { t5x׉],[x\WNv[\Z'Sl 5t/GY65#-܏!^HZ]D\sS_=d]Q9J/+X[~akM8w߷ğ=B5--0{r79_.":Ze&G*;QB {t@/چ`fs~ly׈[kW"?VM&&@.:?l(D 9klvԆdt<رr} T.+]wkvڐK0޲V`d@ѽR*ҷ`"fsTm{oMp[ ?R θB9GpA [0Zmp9i3P"zD~nЩ&00 1EATK{Y@C=Gh#. aD +HPOSVѦ&A@`H$^f1?5,"WF4>۸YHpyeMt]6zdMrw_M w5V|H7rXN$#?:[ xtt WT*@ʋVR+Wv+\[PnHo_Pw[:}A'n5W$dx7BA&xLT >8xԿE-'Ց]Os6Z/5c/|nk3&&Za\ncv/ qV]*8NNzK4-[%`UBΡK%b"LsڃOtnm&ªF"0o_)/ Hք`Z@M<9-N([ b8[F&M f$PpHjpCZhz@Sѧ(jYsz+gh}ۘlA?*Gj* fG&Zf硩Y :j!Lڰ)1EV:j*#)ā5*vTEE=q֡dW4#ށ0rIճ e5[gGz1Qp=F`dIh.,qVgPPv q]eMkt]esvU"@W; 8]%r%@EdLO(Gވ1]>hѽ/9h+€ )}ȨTV cu1[l3zWB^S<çHdkKueQl">yjUS޹Fz?UDj55jٜVTJ `9wS^q273Q Ԫ,bcMirȩYB[5"[%b EZ/mAҝǀ&}Y>$礓fř% W5O `c=jo5 Wf ǽtHkG͐Auhy Һ6,J+R>ݸ ɫεGXw>b?+j-GPj3k2HʡwR vu2<MK֝H,/'ڶ~6s 33$|yqSSͥf7\:OZrA'W]gP}.-6crsW~\L,9yƵH ߤŰvzkJϓuW+lt$~ߏ]'ȌGӖn{d'Q|6:4ZT'WN\LǷץ' oTGSy^ܪ0cu Q&Gqf G#n܍'&"183FjvSlh.x՘QB9m#kw\ DFɼy* $8b1(jųzFBNEBZ9P&T-0vḨ FētsVmTz7yަ簦2A(2H+ #6Lb!C oi`Q:bx: ф3lI;",eYH +X^=>I `@۟.|\1J,TM5^2^jQHdP\Q|$U=e4ܘNOXmWN>_% M}#`jĝڻk+RITTGmߊK@s]NVHPgɮ_CJ'ZvO f ?#/uµ.[G^±}CyBLV+ ̾`Wڡw:+kCAz"މjh8obdz+ȹ*Qē$\1?b\(u6"bvޙo](RHiagGH.I<& ] 2;Ջ Yji^4Ҷ8Hs++8dOyzֈWeճoh 3'O^٩'o|MYȃI?\TuN*y#tz9\No,}z%vZbȀtYL~*^kbÛn?TT;PvA$ĐF:du_}CB+Э"8f$yV>.W2ï{VxijĴ׋Mo[i9|U^jʱ?jN[5J${ո)Z@I&hk]!{k Gn]BU(KJJ6dju/aXVk$35I}'`P "AƦWҺu6㟱JJR ATou`[۵L"O&֟qmnd\<$ !zK`Np+j”Pg:f9uiVջgq^|[)nǩҏ&4<:룪ڮ:: 'gt{XF?L9q?9 XL-ŵm qk*oMweg&GQK}PNGި3黖cdu^SYwdXP/ 2=ĕTM b`'ޤ@ wGnFmzAhB9ƈ hk^I4Vb#6rLTjŸb-*Y-w\H/+zxOq)q˓NLSͮk|P\`sh"9 AP:۞3F)r++ptV\rMcVzHSz59EfΟk5I5s1X (QVSvP34 2zTJ;afdJcK`#ȩRޔn5qU%Oj{@7QN&~(Oj !OJ2ڌTb$'6=z釹hl(MBݲr:U%GYwb>*l`xD{j\s'q'W+]32Gҹyc-AnB'c1m1&eEK̫={QL9Ts=RktV"+tV #ߙ= m(W9U;6(݆jkBҒ#VEԃ3j[1B nyxխx#\QJ-sR]H'X: *@P."*kbvp[qRHL0@AQzPՆ-5>/e~_/^^~Y H;k8i]wI5q-M0/?}-t-ѸAzsG#1e\ \89WAc]:(*>$$U㕩ÌWH䞟˅,$nu?rR<ÏV[KQ%V J69tnٮX2P_TЀjbU/j\mA3ڗΕDž[!*/I#1kIQvWlϯuKݹ6Ĩ7|Mp<(lrx~U1fr\oI{vX T lGӬٍ"#`jc'S;6 #&Үy {-͋eOtrݝ#VbOqVPLIV`mFq"yV4%Z6ɸ?D7"E'Ev8=$3@d9$s@kqq5:;O>k1ip}T\n?cP-#C@9Ɗ'ݩڸ1RA@z5kOnՃڷY!M%A&eYݖA9{YE-$ޕ)jt Cَ̎t'T-+ȭ۰lU\7X`ۑ|cY-%}Y^>vݹy7[)X[ʇ)HVG#=m͢L,+5sy8˚B@0H}o.0"ZL*֣jtzR45K WDT|N#5ߗgWPL 5=ׇףx[B+IEy-ysSqV\]Vc21G%̽uwjKbqK{AsA;V˕|##X7:OMk9_]j%w0$s5@vDWSIITwϏ*Pl+H^L_ŎWk!Ts LQn^k#Y؄C,sk]Enz{UU^qVnA^HNR& >+cjŵv);jNmfa*'hYVTX֨ZkJԉUT;OSZ,:2Itʩj[Jbq@DPIQ;zѩ@ހ?jʄ[ԇf,@ϷmwSTmlM?lTp?R^O,O {_7O5'+4Oc ^k(b֥Qxm`Z=/IdE/)'3^zp{e0ɝڡџp$1Ԛ*du3ETnfbGaiQA\{ VAV֕d&q+[qd ?5+lx=/H@Lvgnבm|p꾧iƷu[5VW޹qW7ON% 54P)q̓^rtOGP$<}wxS$Fzyu+0NMcm-!0#?jՅVc:,O167|2B H$+1RְÑ4ǟiKۻcp?UʔP*:ձגx牺)]zDqU#?ļNDz{WHX g9?Ií倓EGw z"@n|u{1lbJǪ\@!uT iXUwcןymf q N]}#"@޲Ѽ>tܥOCҗ:ʺ}֑b\X1''yx]%؈c&Oz.M0m']#˩[;v6툰Lx?޷]-$3sc}zO5QTy_ɝm$=L 4+cjxu,`T>\'EƭdTލq?a\x~+4](}-z^$%"~⢪:}^:WR40G_7\734D=}+ 8jzQNN=cCbPI\R "+Nf&@HY(ȆphRkjd@L/ZQh&fEDvz܏ș>խ[V &ITb";Bm@%GCFbGbIvX4eX#q[ZLJrIbvYkX;2:W' ?P叽<P̲&DIzO+Cm!fOz#]nT PE+9 RbßjW%{O8D ҋVThЪQV VDuKWuC('n'\nj#n껅g1567P}&&`g*1SS?cֹ|<[/B]y}=~7+ľz{wm 0zzuW>&\\Ct }鞴qJxr(Ncpgkymo…GF: >벰ݠ GFr;{9_ )㚥)rL(Z׈}gnt$>Onxj.ʍLq vn9d5QB]i=?d{ zրm;yPI=JS3PAtvPAA-"H‫ [CV 9 6n֬аY/Iڀ:ԩa{46A4VeȎa LZ8b jhzʣ$X,XA3ڢzNn5}&PK d}@-H<+䊨ObkC9jGH 3h1n͍ 69=+" U3{2 1: wcz*,r%UG3]#aȐkrڰz&"i?T4PŒK&H2hq ј<84jSVZ{aֹұ}kUNtO_jӬwTE%yT`1'+*'XҶؒ#޹WIT_V"WIu$Z\175GsޥXC#)>VꜾ i2[RQ\Nۂ-., #SGNaȩF6"6OSAa$Hl6'F kӔ A=_Xtg&<i岓#v/ Pq_\Mnxo{c.ÅQrH\e^)&9֦Ê`OZ驫#-P(U46-ovdε"ڽrcb"h.@<9<7mܸK{UUGڱeˎXkrCļI23Z:8ZBրa49lPYdAiz4r``Fc*$VY j}{Tvvңg=/]'h_; )8xSU|-\@S|19W^ӆ! +_D> B*r:O2 ]ΥsKWQ +geZ'3S~*į'nG}|k?ڭX]F^ #0~jT"W>L ~] ZQ{ f,\*V49Quʘb $0$?j\F]I :ئtI*A'b6X|4i9`ЃXsr 5 ]܉8=Z{owFz\ ;Vbze ~(,Y7$ul4V%`=X].ߪ1B@}=mn6tZh:4kEv$ϛhr@8GeиzVQ*Q5.;\]1_C~&xo޽~7(7@[՗H*` R?PVs^c[F&p9|zV,iV<ٸ8+RQ GȮ܌Ө31ǤMV7krAJJ'&+oz݈^OWך#b67np\ܶrfП 1= :=%ƷqU@Ͻ5ʵm@4g'7şO|2=ԏm ڵ~!qݏOȭ <ǯ>niAnw|_!rY>J񾳥zͫѪtm2 kXqk8'Q~6}8?6s޾ʹqߞ=U dz~w^^pVhNVktf/G@cv⣋I(ܓڧ^[5i {y{8plTgjFy-pn$UAP@mݙΪLKZ(:%PA0@?jE;Vr*]"*@9+jC]* [XW- J ֶ$>LT> _tY^^-KD5RH3np+0|!oԛ3*,$[K XdwCun*qj鎗.yO+l]gʤF`W7\. Cߊ=e%~Ս[БcmkvE'ژJyxZn+ IjO[MUVf?UU%L{VZ{v"; /pR=Gh/<&ݽ=mHu+EC:rP?&?面s-cOZDS^~}3-6J́{jx:}􏇺b#TD'Ҽ{ `5xMۿT=/Kj0=DOyx%'W~nW&{9}w>GކฝOںu+} ▭a3EV<5G&lFX`;ڵuؓ8EoӒmx$9=>;b1F^t~sX9'ҵ:=T ;J{prPzz2;T4<,:ws+u^ /+( wcn^0֍sH*VV'T@A?0}S{+b`DrEV%%}S#tRv̀TX[3p76b{CG4jHRA [`@ɣbk%G B$($`뷀'#˜qFȊ 6lwB7 d)ueMkxx&?zQǦG6݂ܵwhN3R6=WȞ`~~}?ߪ]yen]TfZ-Bڧ 3k1-@%FV qAIV A(ώbm8QYQFmҦKͰ g@?u`!޳v WO~鞵T:*rt@ܪ@$Ib؀ WhTC{m N*l&VKDk_8]㋗b'3f|zs̊2j[kBk Nn!H>ABH3ڵ; Ni-ށpb cڀ?P5ƄH恷\tp{T,[`([vȜ #elI9ɬj"Kwh@$4$`zhA#Rƚvdr{ؖ*AޡbՖ&A3RʰBV$bAS$5#F’I9=&]d4 qE$ r( p1hz*3:ɠH8YE#aTYn5F lܤ^v7]%Esz/0>Jc'R 5W:`WXF?Z64F}ZG0& њ ZO:g\:'zRUDfEqN4lY'":{Wy6Y^{]#|+DKeH?9yu1Z"$ɮ6HF\kVjD:277FQLmfՎ MYX~j ( KZ!fp ƬH {VYTO?DPu%{5ϪCiqk':坚$W~gشU²oֱpOj=5 *ۭ[+U ]"hzH-6a 5G:2xˌ${բc=J' Ux gN&zUMCo,6f&uOXsC=uV_@8]1WOmUO3ֺJ\W-nC_ Sshb'1>º;? sj9N3?[Rk^hbڴޥzN~¸V iF#"2'tn ?jeul_mh568z[CW3Ru=dG~Wk[$9k#>);T!{D1=[8Jf܃3=oo2ju-H'?qct3z׍ZrIQq՛  U1@zڪ4U#)nr\XZA֭+zU2unp05eu۫)VƽhnIUiZ#IZTh=U1Dbg^MF1sYE[3Y_BccK&=y :: MdEauq1YAo1Hsr#r. G}z?^e%nJ?;j.9~}P3"FZ",ǵr{vӿ/ Uj.#hl`Lszh D,s֚ \=nk`JȁJn'q&n۲"aA=KAb?zKmƐGCop*s'C[- d=T*ghZ(nI]_ǟ՟AZ{:q#.HxY^>^v9U}nr Isڢ)WWno@C "` ]#OMi]_rzq56z ޺==g 4zlٛn]fh D=tИb3Y^2FXFUSqkJn"q AG_oi!GCrA x<<ħ'&WYOcO,(Z{?J*+/nw~7]Swd=zz}=8vvnoq'cUK~;c֗X}`:|}evf͋U츅dgf&Fg:ĸTGx~<cӋlD3zo[k-H_>_n፧[j$9#S|xB꟦RGq<~yvKczqYtO":.Кd<*:_Bq3$խIA2dc~V 5ׂ=U#sü5`'|XmU@$G^MZƈk GSE,$f3Tʽm<}{T!ZoiUz5aE&b{cx0z"H6XNRիigjhdySFH+(Mo֤ NOZ,Z!y4DWkD=4\KbpiZqE*^G4D$Q"뼈0+ [dk ֺ4z3cbc+V% ?uXeʴc=bbVA|V GM>ՋSq)`&GzGY5Ǟ\t4H =+Ӥv>E!$^{]$u~mRby8Fl}WY:\kNAڹWH]._~ÐwXyЈ TEVI2[80Q#b+(6GTwXe3Q[-FR¬ލNˡ`yf VX]?A rZA`TpSY2sX7L1}/g/@>hG\eQt{hȤ6']9M/fJ&D}_0vdD][FRp^2#K}7zuCںkxI#}=޶ڽ#kpw$?ҿW|}` 08kˋ:}>xqoUjӺ+Mscuu~6ݜ<*Ҽ!>_ܸۭvڪ),IR5hi4)j1$V-2eg=5jP}Slh׵e& i}ןĜuYW-g#7hSU-pXZKm 8YAl"QQ̊ sF`Ad=rGJح d>9OԀOADy/W-iIycK="+Շ{ I 7{t1PHct6bmaOy{RիXB 8xj<8-k`r[l`Oo~96mņ:d\kd7nFNN5 \ma );'J mx@d)}z}w!ZVXU UΚ[h" T'^uÝI*b7lMOZpv$޹z}!.xWT:TZoXk+g]pk#]>|"}:Y6u9hKxV LWñúOF*Ϲ\wW>"_q}[ի6. AYj_(Tdw^.?M|_Wh#lt j+&Ǒ}QdiѼZ=u<}T4mVqllt}2)vDq"lr O`(اcJ j:G_pmGcE-.Dwӱ"]uہʂs5Qʩ=\*8Pګ+'b'f{QMxQGJ+WjzѤ$ GԬheN:ç.G|6ޯė*Fz\m Z@qp%1GOO~TTI 3@EcOZ TYP*2`Is-nXF3XP"~ c9&\s:ǽMj#~ m\/v`Ҽ#W;|:_rHVrc׭9ōI;f[f]>>lrIx_h$Hzq^NjuHl7Q]- 9๴D[H@O3KA]sҹUtv[MvV.Y*q޺"yGOj/Me/61XZiw ҹH<2Ȟ\TvZ?;Ѐ w\uGтq .yu-[:Wh 3u: 8ОO5-X?tU+],[ўKtZfk ~+bY3Pd܄AlVD1; Y=aZ{ A뚤kV^ Jw<<~)9~_-kq5~#-q]G"+6y}DnՓ%phpkW'pAnE\zY@c;sWւkZzkkj3o@@ 5Fj֝ٹ{LE_MZM]$r$EںC~ V# r`1AU]drjիŻ~N2l\#`va*b V(x*c,\Tbm;`qYs#ع ׭f&QfXW]C*3ۧiܳSvԄm#@ՊWw¸6 Ѡ]Y*5E֠vKOab&8Nk5(Xc 2Of1bmJ&k Kw@t6n8M0E* YikoڵpL(Vusgھ} v汍@ _~R ?"G3#QIi~h-k("XTj؃R]ˑ55">ljV(̒#VbT[j6j["֖Э]-RE hx7eϰ+GLg4ceY NzP;[?Ol;Y- HO]9M'>p5<_/N:] Kv9c(1+HUp^/.7V6X&G\^#=_AK#˗+T^b3Je9w5~!FvcXmR8r#ē]p꾀rݫ5;q^~_W$W?TbGUo*,n9=ABTw"GE5V>_]Q UzSѕm|fݵ@{z,$@FDJr3GZ]A nG_֯M]GF g-2z)r[>FL'3?j{<7__q}S&'~hij4]ր >kF}k6R`i1ďj64>֭oiW @'[Z{/XcSL-lljJZ=;UȚkupz ~qT4;T*>Qi4NdH4E@Z o[ҩc Aۙ5IRk;[ 7.OcCS}GCCOi9{԰:K 2ySSn I+uOm/=']{W\z*(l9'|Ǭ+(z/Vn^k)nyg#ڸa?NC\yGkx;\ݣ$^ W4t3Bj(-DXD8 ҧ \zE>bTOf./XM( 3XK/vAѸHdt'1YUZOzDPm V&> <<,ox:56iY8L|T0-RKJ)8$f=Z:=IpGC0jklYO!\7&zV* **:tZ]j!]'+^Y;c4po(9"`j8X|,o'CKfZՃ#8kdE}31ѶAb&A9޺ȇIlb1=>HuW۲] jpyZթQA/,ftšn,p+P*zpV 4>WhD=*@Zwk]9sdj5@kRO6` Ϸ}ObٶI=&U͛:wuŻ.Ix`V o+3_+wT j5_'[_b7.+۽9UM"R˪WgMa:u D'q16IA qD?ֲ+ÜqX8 s޲b`ZgtΓ CD@iAѳӃE&Ș,Z,e5cFI[I+KE, #oRS d 1ڰ}YYA7)ȂTZu ݆V=Mn݋Y>h +& o2@Ѥ^X1Y[v6{ 1m `WU1UxҀ'MG ЛKܟW*,bxoAr#q#LfT혘S@9`wr Zn\ TVK6-8u; I\DV:[A\mub^kzִ`s3^~ITWiMqxDv8=v;z$wvr4\+^ r(gHE-=x)NPgiWm\Z"=P2"bTUV78DX&NXt*J#ǽuqn+~>'+gH=|Ϭ~k%c[+62Ѽ8Wn\Wg'^kp5}1wjWD51W\e;I wD(wW#-_VB4n,#[:q{JL#tjw) !"ĺd+9ZyGgW\sf {UERς V#]Qn@$$D~M,jCV=}G>~wH~ޢm?S_7J9d݅nG߽~w397kލ.`I94hv\F2Y5*X`'jpv~k*v%沂@Xdwu`Rf.o,GQC{F>٣q$K)jkDX0OvoSփ~$UfRcV1ɾ.-zϧ(/}!z1]kz/K[$\R&+'%lUpvP+P>ǃI Áđ޻rpHc滽qQnm:UEȯVL1=]qJ3rXl[` GڽFMv1";jz_L&csy{n?S2& ~6꤬Ŏ qYWkqg[KOk@CI\mtnfMT嵏K%[`5^}tuګZE6*LW|ⷝ/ d.<&@R_['[pjQ5^}{:|Vb͞ u5Ǿ]~ zǚ}YXfURG<yߡ,p/ :kyZ-mwKClɃkOduu5шG[hQIFˤ`Z[ qꘊ0IdXM]c /z-9'Zkf:qVkhu!pdUz}R +y/#U=U ׷ڪ2iaH䎕|l&{V lDA*Bɸ%cYD T$+\lbҼar8ߦ_tw&2z;v<[yo'n$8 2x3DJ4ݱ3X$~P~ 'Wnc5vP9$&j]Pf=*uq>PwOaV!rUbz5I#Bښk K@aŶ cGxkUj]"BTV׃?:Klu6ŻŶ᧌Oy{}3j hμ}~'I0;XH{R<@2xG/Mpg,Xt$ESh+dW1˪~8f.G_/i֡ך4L9'zyEs~` jk+cOFMc4n*zdEZokqy^>0M:+?{psl[03 9kG8~_+ny5RџBh[Aioi(+]%EfK qꜬ|cζ "r-rՐGgy8uƽ[bLdW,.lTY\+ku5μ]+cݫt!ik5(*ӏy? Z[l1STé4kxgf01Ws? b09OYU)yq!b[$L|oq_#yG$>OL̦6/Q8`њڱ#*/_5x+B+d{QRYaO Ů)3$H3g$X>=[b^DUPK$@L$ (A+A69A-1v`'@K-' 7A+8ز(h&9Fū,m(nCm=#YR|v=y>:Ir墰 WLyz@E}eb&kudޙ2s[L4HS!QE@PB!k2XVxHGNDk[<h\)&NqW/;xW_ }u{eHQ2{>|Oksȹ'_׫`woDݒr V2`j`T$AjXu6\dx99E/՚h{L{R]|Uʌc 69e,m]cc`=s9JrI[S I8e3IEDd02(pgՆ=&F}{t/@hmDQqhJݰk+SmޥX Dڠ::<-D0j͆f*I&; R{zsnVsP%m%qRU71cڧTջGz QV%=YF vw2:Of'=#Aan %C'F@k1R?5 J_Ms\&k[`-'(I1\_iZfqj]$zv[Sέщ c^ҍ[6ە\>5REQ*HjȅPDfAEby&A55B#JDB=qX=(.p4e[$|MlBω^Q<~l~k/WTe0WZ:\bD'HtOE▷JYws-A'} : 9> %Y`TۙݭF2kχQk7|0&GUgۂ7G2$~>uA$~E$ʛ3zFz'=GȦO8 #|NQg0*=<.gŵgT]“ |Wz<>z +K@_*ݯ&}8s:^ϒz'*]4@%zt/"in dyVB8{ztQ\dµ0+P-4TKoR:e9?=O%$l V%f܍A:GLI pU ʀGU#gRT(`kQɠ5FXtID[#Me`"3"85";Icv8m1zҜڅ[wnѴǿ5ϙޱۘ0xRJR\zAC ;Lb([*zG/HQ]c>ԥuYm<^iF*]TmI1M9wX6->d@+HHIm(=A(ZzC34?SӴmsX:`Ik5xN͠s9 xSuZ;{f` $7o t יu㭍b:[`║O֝[!UHTq3=U$ms {U29mf=Oۭ[q7DOJ*@yT'b jW+sCzϥDH;`{G ar+Κ$v?ӒLɉ0*wrzH>'AD/h\?ʛB 3.o_>y^. =jcOJu&\+LrW V7UX+1LzD[{vm ubx$3?9׍ޮ|W|X%NQK NN8x(Ӂ3^hO> o !IN_#My!{6H޺m꫙q\⎼֮ g5OZgM&ۏ{nɉÛ}%I,fH`tݧ[)m*@&N*1W{W]Mݹx̓_5\6R Q5].'UF-Z+[" ڪ2 ϾkQAEtk@lڭ&{jPWYP2Oz#aj8 K5G;Tnt,w=Ryb92 c2RKp8hU$ ^ 93ٰ-i\\F+5 5o(&1ޚԀXbzqEjM V +Gk{PקZê_X=G}ɩŨ"5v *** ;Ll =`+XGjpYr(,Pn}#q3ڍN7vXK0K3A{Ml_TLejiaOQJղ;]9Q\tA=G5/~z}E}@ki;zW]u[519syxˆ1k)#`?5\߷>4H~E}+-m/MŤs^7SR~q5lT$H|: E\f vtQ9]t'p4V6WT u"fڮ%kKNA>UJⶵOq]ȁ9x-K gwZ䷦uu7J[t~CTEOokPk4P1\Y㱝0ګuBrד.gwv6)WLs26R5RI͆aFbn$Z4s'5nP;f -=@'R:9k$NHkwl;'q1؃|0dU9U5ZK@{( ms6Y˕2TtG5g (3܊ڇE2˂F$wRBMN ~K7%wA6rk/~=eHs'ۏOϺ %EBS(O+A$PJ6ނo|QtPGAdb{رm|2梩wLU4lCz@ svs 4k:EHV-@&xճ s<zH6`pO$z?)\,menu ~۷p!b:㏽zq˧}E.dIS_F<1>>Tz' ZKFsi*#w>ձ/v {?P73;r^[qL=3pN85Q3s@ afzWiUmv`d+=YnbAkˮ7~=Սm0 Nq3-dcּז=@tsV_C_WyzmM3yҟo=77o!F2fr "}=ԭ@ ;..Um:z4̖`& w㩏nW?NL~ߚy/ۯ<9MMؓ^[Ӭ뵬UU9'Z.JkIvO u\GQBju6m0{GW̯b*{Wp2tz aH_XETGZoee$=p UUcg3֡8MHzL"tTnqPQhdI~7:;QvF݋ܘ8+ѶV=5ݪBTWqfX+0@&'_G}wYdBxFT5yHfTExg$J_1Uy;\I2$kx5ՆXzs>!k,`4e};WG; WؘNnUm Z; 9uhVH{=ֆpJ/L]7*Vd:_v#+*+CAM=gb.6vny"'G;ގUPhFXJxFb|;Z?jݥX4f9>޺HuZt$MrVjֆPMs OJǢ}-6an՞3֥ƽgE=zOҺQk+j#=kY)8f\ԼXm>梷긶IyЎcž ',in_h t=2Msyg/GגM!V|G_i@B>xz狝yV3=pHTH_6^H"ǃs`n`v~sL11[\*kӚ_J=>>zhȨ}v[,L4zVK̠l+boZN6q.Q+0}Tp .턴 mS^"t R-AVآzƜ A&K;VA"r"3"%E (A4G'ZoM$@o '(nAl\賦Х ˠJ \Qry+_X'e<Ԫ F~j򺯧YQ>sJU&H\mMe;T4%ɠ| LY6n35WuK;b-* LvU/󜁏sA]y;VRm)'S wJ''5 ǹJDksGĉ\U\nVvƲޜu]qVI"EuUZZ&A'0u>hkH }2?J7 oZ e$&9O#l1( 3CCf C 1i E&>PӹP5ƍL~jp$~jǖ T@ڦ.ZBTU- ău?G^~hqi!ܥHhC|ܔ9DKtcڀW!HF戈M]*l#ފ]i4{>:=(ڕ`cq"9-S(/Q zgY<i',dՖD@VShla{55F:`H=Mvʹ 5t}9~5a\޻*HpGZ-ٵ' VZ"GIv*jk[jp pAƑgf k3ȊYhr{TKZa_qst|)Luzֱ} \Vybj.<\xGPKeST }YV6EW``֦CzuY1rٙ5˿n^Ko%_c_*|GQ;vE}%xeڣ>QoND*sՆOⷒƆ ĝ^+[sBNGzNo }jHf\+ ~d^,I0 @*}EOS,bζZ@ݜ]F,u ,5 ڨ`GRL"1zIhjX=Lw_eVY1L%]F>,pr*/ZS \{~=?]U ؎WEK%HE3\@k96<W&?KmB r IzP|;MBcV K q=+`_Rιjߡej.`uQT<> Z cT-uLʨ3ߒڹ/-oPV4ȢR[na:zPCLn 8*kJޘ%ǏMBۙ3DUV5Zl8I4׀2"HCwµO1IGֺӧYYEI ڸyox<3st 7$~U'59<|USJ,E|hfz);^JӿVC`ķi(\֥M=4ԏZ$QVzkӥ\w+({ԍMGP8khDrGxJVJ6 U9azy7w9WmygY!^ tW*GKk6Gr8z#zizC42ezyy뜓wf{]ezsۆf0GJʻ]kNc :w6ڴ+g|q |WY9t<% |OfncZǜSٗ]IҴ>gLsP5m Wl?z'5Ed/$@MB7d _nOΧ|$VzQ+f%L;H51ܼ[5oTYBIEE豯L'{h5;=z&DSXg718ϽyZ\d/ݿiVGrA|*K ?`H?5*{Ftڒ =1E/{5#=Y;qSk_ ۏ;WI#O p%`}V5 bE[16 Ugڮ%3NSu[A?U(70HfMTex`WI0MSH26ࡨЀ U|9|OqX+7T\+i}9m4+N֔;LZ;zITuQ#ԛj&5gVn""Qx&f(xW kҬA0`d׃<vw*?kwGkRIi8<ԕ>RdzkqL@=U^'rm$;|u=:ǛxIKwCi\v3\7xJMPA;V*&n $ s3AIc"I$@8 [1GX<& lh㘬*;>jmCx?c_Jl:։U<}/-}?H V<=wd)R77p]{XJ($gW} x5cb}O5=9[6NV+ =L0(H-=Sp\uZyew#YB1*q4Հ0i5?#if8OmYrΰŀsjOj+&|dj1wMF1SIBr ;+U1fceo/rʤA px=sDx^8}\{'Z.$}p;:P sV8ݤkhֺkmh̨b$8zs믨O׆ Nj/LJ7}x ᔶ}~fVMA[s^>]iO&52h'JsBr<ukmpSmΐUG>iFh{Uߖ}tt=zsV9ǮXYKX3X LJZOhyr#g4xS$j:AAhAvEB8%iEƞJ [9tii@h$n-cEavȷkGqAQ#U,'Gnz[D ڌfjԶ'UAх?tEt(^J(4D 3MRX$v60k+peW~k Y[ʪ`wNhY[v\} wNa_Y`-Ǚ<>~>x"Z{nU3&:>S(؝ZLDаV*xn35+ŵ>a0fW{ <"80>h4(XT P*1⩌Օ [-n#>_AMQߔQ.8'y}9z~?O|z̻T` 3_~r9 zjV uVטCtdlߘz$ ;8MB&AUFX@$ 3VX!yn#kVo əƲo4_*u y]b(~sqUAuc 5I63@ڂAVgѸIfj_zA?bwmFejLVt 9bi 7{; XH,r@'h(2cRtYTi7<*D˙eT+W|W:Ցpֲ}$Ӳ 0h錃=ǽAwe`YAOgcaF; 4hl5WHńt;Ti(*kbC#sRԼ$"gA?W[BIGc955nטF*+Z:{69kAoHmfTȚsze W~+c>f l{yp=fN}io`pG*ìDI\kzV|녮-.A1+}-myH> ^G~*-u- @e\s [$KnHGůieN64m^'w58.?A*M!ѧv13=h7rNlZn0AޥM[ XdSZ8#l5Yt z|h5c2GJOğƴYgg;r~+<|SVƶ瘤ڶAV͑^+KSGnR1ӛŴ*oqg4=[ba[1 T/ɪShףp».W'_J]`̜{ OnSyZuDպm9z{R D'SNʡAjoM\,(8qr%r#2kP6"?rTv ̚I~֗Y_W/NecӾt"15tVܬu^m)m v3^n5ô2Iں!}q=`C#0͂ڂw/Bk+`*u?ڹEwW?, 7 ϿjDb]85 Wn U&ZS&(iHls(rqƯRV~ycK[tW.FI FWkG`jޯxګzއ|Ϸ/߉?"}xI } GzY+-9 gڶ ҇LVqcvkSLEZnVVEw1$4-8Y=s0ΊF)w@Ô%I@СcOifOh,aF.lDڳG{QiS0Lt%g|Iks,ZA+'1=澇8զc^yj[Kt'ZGiàH2};fmWi5Q}O`ٰR?==\y/ʫŒD&^9s0?+uֻsndgr|ǦxӭhH~WFtgyȣX[6jd\ǧױvfgR@'Ί%J5".#qIXC+kϟoxms1]oDY\Ŝ."GqǦ=LSg.(䑘G*#cSo=Ҡ4*ۄ hQoT` ?*zǰmxmBZW SG>.@cRBH67AɌ |E6y}uwTPX:8ެ.Ess?DDS{Oz h`6D7 s\y[U}tNNB }~oao1!!GJӻk'?N&%.:{ק_g!v `; Wgk5CRZI'QHzU_^ 9ʹo!܁'2eޣi8>܏ZIvxJIkYw0Rr|'^l_B@bqWwZiEe3ҏtrDB|eB!g=j9Z|FkP+cڛA'kA 2Hڀ"sIa3R#WM61N&Yl t¹l,XKd_$$k4w.Nܱ&FXR#c&j:`ʰ4rxD!EaԊ m(7 QfzVV-${Tf‡+Ger{W.k#%ݠ-J/>_}8> 5x#L*(k\UN*Ghx v T;2yvTq( [ UAP*@ʉ9D$'^(trLk/I[n\AŸ*}iۏ?Z{Ep0y_~ߣ)x֮7:}=h-!s"ݨ[ g ZT.Oڶ%JHB˪ j*S`#u7|?Wek/b"HYWm[ڦ[59Z{ʫ1bʼnd}Z)ME܃s֫R^l` b矊YSibOjaf=dZk1EY w ZH )3R&'FA3Co@4!މ} -`4KJGFޥKZizU/[` ԉFMeT6sOP8{3SZQJF[tŇKOżٞ#rWb8Ұ Ag ]+ [JN@l]r7{T%ѴSv2 5:sX4ͨaI4Tm=„n}==D=IKRG^g$TheFʺl$X>/cx Dq^yG6%漝GfLxD HLJZWh*mlt-;[rIVF']b`ۉUpuP }_5X& z{L$g|cbʺm =F]YBS&*rN55ұ{UKɚ b> \piF IJg"񕯢q Jmp'`cZ0'k?5/sGkkq,1梌v{Ik1u]mzFkb=5ZarvkYꝛ$H⶷6s=E_?Ib; _K׏B;εnN 5rj/iખc޶b\$iG h=y5)e,; k1vѸV *+12ҷ W#]ћvTޚvQLst>T܋=CVUKqi\OոZU #Jr#`2G=88T'tN1[Nنĉ^;v^/zSA0ҠNk+cGIbVG߭s]dVu!(UqG_Eb2>b 4۔gjW| 5>fHsQ@!&:KX!5Nu4s>""03BƳR-Bt5LTl@0bW==<_JF&A#|zUϋ?A&Oz=p !L&-hK6xA1(HTN$:m-UI+#|ATJ8jƝ*ƉHa~j)[EVQf֒~*(СwwY`<Xf5,i5,Ol Yyzy?wJQ'_K#Qi7͒zWW:>587_DhU²Z< ~huK1En;n-ִ7Ku21?XOpmA 0:bϧ:rҽ~Z˪7KwE'cWGx3[r2.,Tj*x3F@Uj/ݿh:zn٪iR-gxl|j ?o5bm9$Ǿmr~9j*7^]K9 Br>LtFqq|-ZOݾۀfHa"|+wz/,->+|Gjvm+Y. ?3Y+/5B s,R`lɹjM˥vmJ%IVXIENr@C{GhAV DDo(UHLUcm2-:5X T>\9]1k`$TD:hzF_Tn}%IuqX(Hr+4+q$լVD0jIH(Tԁn,D7@I %L8ؿ2]D7SұWQႪ5 ׮ƺm 9}I2ӟl;[ yڎVCi&=fRۼ:ixfk r-m\ 1>矯enx&e< u)lI2 ǧ3\ U<3 +' Xi֦_eZ#1k]c[e O5lpI(J9e=(UJ̧,g ڂI4qMӰ:O?.ufi"z|']"_m0KeOibګ.#T^Y:7ZʎتK~SiW~,k4O+sK-s.`\/pK"P# h5bv4ǫu+`ZR{rܓM/RYަ$<* 'պһϵb {M&Ys l< i:M6, 봆h%#'"sXF f2$E5D@YQHZe}M2F6lz9V}ۦ'ֹSRIaw~ ~+Am ĎON IVQ;mA`ë!]2M@+B\ܱkEE= G|?[`^*u7EDVU\r{W:9srӚ}Z= ~(: UV@Q8mdD:HNXl5׏E^ʽsoq]]өJ`]NƄyp}*Ѵ$ ]cN$WNU mrX樳C7$qtЭB$5Y=OoSEzV k&jo- H}q-؜%gMVM}Q)U혴j榮mFx4Ix( wQkVgW|}G=}=ڱn*}Mx9ךp^'tfzז9iKLi?ڣ285 +<ѫA!=jV#p+tă>v JBqi!iػ@JWe y+, mt@5,譇d ULWlZl4Ot2&j}P6֞鼗XjImmXZ@#j-+3o#G@{.\<_֭K@=o1Lsζʴ QK50NL@T*w\w NOJwP& ٺu\[[@{VH&;6+ 2sMB7UbEĒT~ծusgaq_բM27%]2p$㚴^ʨ31ʟJKa)n- CG^Ǿ[j+* k޽~[<' S_;Ts/^_$f1PP?@Ƞ$fd_S@FI_P 4j4QQ+h/ @X.%5@#eTh1Msk_K?qS[,=FMƶzslx}pOQ TAͻ{ژ*H3WTP+WYvK|WzyjC4'9澗=s!%[Z+.k|fݸ!ٕ9_Khn!fzI$n`3ߧjv7K5;)X O+?Wj Z5{y/{gƒ5H{(.Y@$Ɋ:ZN-o ھ^S}1gBp]@/|' YZ :[tU2VDΉkB4ցe9[j_il%jbKȶ~Y1ڻV ƾQ 8bTI ₺ݺz0=AQ*i@=h[u">"f#&+Su}ٟOP*\K zȊ#EŎ X_(3oi7Pn(m*d2(ԋfkrH Afݐd#梧MŴKoEdk V>G+n.r&cgθel1?3_߷{ͼcת` #湹-3Zk@vs5,u (91W zV'5ǘK7"H=QsW.Znk1AHǽ`I58&UV=ey[O+5=YD +] \h?tj]K@A3St[ABW'k {?եl1l;id۷cQ85D>gmVЀ \< GCK}DŽ+fǢF%묀mamg'l+,fkmZ;9$wu[3)vD\25$?eKBh;)pjAVČ xtxNq sοBV[brd'ؚym `~xAQR2kR-ڎ ŵg{ W1}x/J =5jV@=J b=*kϾnۙCxNWvvެ@GZӗ }LPuUw}=f=w?TxaNc5͔bbZ*7œwFjAj~ T)IH }2+q ˋ@?5qNRdieju[$j륲pf": 9?]hhO:*hio0N*8 sYݕ@X62 ̐Oz 3l[nzP(j[ jD3Vku85;091 т@>=`^S#L¸^jv &Ċ,#-&r@ɩZ,7:NTr95KXV7E_ӷih"x#VjǴX,6 MZ/@ X؁OP gKpq q4ZTY$gFX )y] 5+L3B@GH3+V@@=*(2O5+Xpa}kKMtN4rmZbX`s]sWj\HeA־=HCиlj鬕shvCEqڻc G@k+ Yz]"ƛQ I\Rl^$Ƭ UY'TQ`AusUkBzGvM=>ުf2Myz[ x`]Sޥq+M.'ڡ.ZRBwߞXmpgWpFl `Kq#Y]ˏ:f; YUܸXm][rvܯ&ub/zW>T=G>iZ&O+o[KMO޴;0=jv23F 4A\qhQwFq޲6t \]>ڝ>3Y[یL:7榆,vYMP0ToSмDR;Q5t+sy˖U<#⽾(Y]`Zs55f%#X_>.X"qhM2Az665M1QzGļ,r@c\G};j𗲤v׼+Z|U`~LW>]nIDZ~Tz?(C\/vs&fjYZVTB@5S2AfI|LOdu *i0}oE9Wi9f y>- x|x\Nշ_7cysxBDֿG?@ΩбXPǎxPP"~k0Pp9D@$(jMcjNP #+1:Zhd֧GYvu1zj.1橌'NJhʨ`aBx޲= jݳK`UO'ښYYV< al?ҤM Q}- ~v*jmranγn kk[csQG/vZdf- {Q`G\c5MO(=pc:.A꽁:xoZ..A+w6*cZ_P+ qRn$k+p{1\땏J*ߺBŠ6V>m;};X<~X/֑bҘ9.mE q1U\|Jv@Q^zy.Y6ӷxw`NEuw~%9f3Yz@'֢v3~#_p)6*:d,Oyzbkx=j浶jYVKNAzح`sq֢;KQƜ.$VVU^I nc r/G1qm2I$zyTYXz$5.,L QrWgH:M2[z@]+jg 60"jIPT׆)PckZ7/ ,uYA*"l:H 'JlxJ+::f0QuuĮٚ.rꈙlzB0T Q6fhopOPk-f<+0YI{>SϳuN7ˎ !}_y}zvfff?zU>Ƶ5BɏsTn2OSWAb :S<(mV^OiHb&&{(Z6~ks;b1]cf]1$5h RB$2:PE j&Ջjj,+ r=_"NgRDp"$'4ف@ N蔞 4"v6Zm8=pqA {zbǒS[+63XՄ 榀K#aֱfRHU2jE*;*kbݥOs̎+rbPϸ%(Q A'=j۟l =j#[3ְ%0犝l v<[UkhbF jjr%AXШ1Mf#h$5j Gx\YMemm*J8=KEӦ` x>*Z=dULm,ssfoP#G}_x<1^iA=K[lnpi+N{)5箱b3(5FƋm`ޥkbFݻm[bUEԂ {RsWb%c8blָ<on&xvrb6W:BdG&spc5b}QSW_kYM'#L"FfL܏jPX'~޺I߭]be$f Ȍg#VjCvҰO^T1'Y՚mC5`Q N"qP@Qwd1+P֏umNZ3lfV"DMҲw9d*l7j[KkHQW_W_M2ޕg@%޿;:}?^gMB& DytC! >xy=:zsQF9 3';~i(1ǵ@hĭ8v"1ނT= zLU>⒩qSZ{:g8=*Ж.R` u/}RD:AA&xۭ8%` My7Ƣᶬ/^ǗxY ^[M0sc+?F64o)=$dѓ7i|:_BmM׉ɑ{vn1ܳ?Yf|%\B'\/31|WuX;imNgMDN6s5@_Oh$TY wt~+43Y$OnɠܐڂKN?5LwHΛi'؊^;6k fs_]|o??@A|yǨ*zVQUϰ?ں Xpi'U@ y ?,]vn&{JCX[ hsb{}i$,Ivo}leU aFKFv$j-~տ/tCȠrGd{[Ku>fmڹus1`MΠ|պ&Xe8 `v!KҲF&яZy[W]f=WsWs{y>9|cp ~jH~*-x'.#n+Ww%Ҍ0 +\/k݇U%1"9yߋXWqns*1\uQDyh OV7C{ҌӢ[M5`a}۹{ y#>UsV+\R`<ɢA6^o*9{%/S R%1ID/˦d "yEeN{MuZM[6<6-`޹g_K/:arF  a$q+s]Y)b4Is]#N{Xe27?rD <2.<]ޓ*vn$i{H ' q ȣaE  :;hUx1Pےc޲[^,ǵMyZm*.K6TWK`1:/<Jm;8 H6jkk3$EkيͲ>>1N uI'5X 1\땎s˴`PI8_C:se@''(y{ZFDQ>Uau7|"` R'Oު>LVn\ OdǽrSuM+@j{%3B~*uB12TݸK0YY(T\bXָdʞO=dݶXv9y`1TyzUBLd'QF4/Hnްd@GY]Uf:M{ f0_Th짘`Lj p榽a>$+j( nXn]&(2[ӏ Qaf$ <VKyӜrh(. Q"hYHCma1kpfy*A^+\RjCL LOڤi0y3mjڰ z-ZNqr^Zp1ͮwkhO4۸Z2}~;[@DG~c|~ݾ1]s5.3o"L_Y=f2„$aUD Z_w#5D귱 Tʿ#fqCN}jI$4GRjM}EA9nKb"[&G:ݸ@޺G*˿*]Tota%{WH.8ԣt=hLF`I8kwirsB='TPf 2Fp ]b Z (ps<5 +}њN q]8n]U:w׿ER]ZBcN>k?uapq_?O>1 츠ǽsuz[eQ~ՠzD+2O5 :QKHyfyaӥnr{Y\KG s_O'kcq}{LQ3Q[ȓ Q\VjzfZH\]3@)ǽq(.ny1eoxvep}E[aw9UMKXk]7Z*w`v6%*?zs:n~U1'Qtϧ;Xs_O^]ddWj⟅y e} 5] dj [9 yYYEmH ⹟;־gɯyPXɓzW?UTذqzMܐNjh2#-{*u~ƄTp\n(cf&Hkv':uCT}H$611 Wʱ +kH>I{W#4 UOoڪlEa_|˨L[E35INwV o3jY+<ګז L@NGP*R3X%QA튔l?S6( p3" `2ztʻMn=9gCcĮd{Nk)'ҝijp>% =s^7|U P;GZN7۷`]#|W^/?j]u!Zˑr*TupjV~(B\n>Rv0P3`hH@Q9ՊwL4G=芯p;&Rh#ME{wZ0Pݻv`~9Í_oN{J3@V=66ZX<ٸTR@yG}I#x;PO\ҧW57#L:|hˁF]c tvW`\k~O7QzGf @oJUvUXQ[V x[]'ْlһ[*ypbQH?hGKO`\B'ܴǮ#Vcwt+0}U[عQںG]yǒ'б,vڌ/т'*\v?HΓYgwuìs^~5R;qȬx|t-s6]}f9|_][p s҉yZ) ۿSo{Y){j}z-Ftof~Xʹp{(߿SjT1?k179 bΪj 8ɣg=a@z:dkknlyzMEqU/QyD?n@ Td :r_k:3Qmŷ4CrHYӣ(zut[6y5/O[A<|T=s%n nG\gm DLEHH.;XgCrAp?hG7Hj.2Ecuc'6T[dn)G")jA[$d֩ǤYOR֎4%© .`jEWB,FdyjHHiOj[tukL5͏?jL^PI$uI6n}#O-B &+'^A)V0k*μng:\`OA*fF.A$k5 }# EgG~QnB*R@ |}\|U]Qzj.&~{~?x漖,LIk=KIU9v+Q2B5qNZfA] -!!Oq@M[ RhV2Q5BS v=*U/qȫsQ 59k@r{GM͙1G:44uG2:Q'PS&hmř"ݕaXB5DE{K=DͣTm5F$m=D6j4V"XI1[|Y'<C &rEYSdP`"[nqkdY ~(-e,cmeZ,|D`.҆A͛{NGn*=ctHi$"&;Uq$dD1PVű i[*HSj+#uX IYŀOzbb<+P0#PEQ~f ԉU3MC2'MR\@R,SAm-xDPvW:>EYs^~Kz^^nͶ61|tr7m;uzk2Xq\a^@ =8%XW4H\cep=UT WH\g,9GۍrSrD1zt˴# %zwRZK`*o,5~+5x X⚤mɸ5*7O#ZR|ǎtU7*]ugNAhdw֯[Yi9P[ s?zf4?K%+m1wT@0qS0}IC^{zQ]nY;$U9Uz?[\Vsbhëm#L'WY,%0_?׫>1OWngr3O_qumW`d+3FKqނaGZ3 d0, }a?zU3 .B@DFVz 7[&N]d`LnqhU\jR'#r@̄ez?zm$OcrKfH> >0s7x5"Qޭ[M8V ZK^}u8W:,u]q_'_1/j$G|.?wbkFt76 N VĞ&7ԒKLV)KhĞcFĒߚ0Xd9k7JϹ%뒣9fT?V#p1&3?T^woRʮs23^>iTIM~y%l{}{eGc\@#PSP!^ {ՋOIeUL;T8CNu--y~w \mmzWM=l@$sH-t+E7A9.\}>еͻXnqݕ# `D_uXeTyVj^H&zѶBk$wz;}պ6kpSLB崤c߫-ں~?5oZwT\`J=xTŤ/wM`JH'W^o~?Ͼ%mCfdW}ua.ޮƟL~9rۦ_]ULlJX6LB$!yms2ԩXsSwI}$D?r*㑞ڨuGUlnkMfjåR*NGPn@9NOz+DPYԪ Ƒ@D-Hh@<(/"=h AoXͩi E&(/'QVR[h#$4q ښ i`5fn#ЮR&@5jL+=Jnނ)*9[@s*ҷ &'[@SNDqPABd $INܹypޡql)$Q9jH9PEXOZkSV۞[ ;j4 A%v'={qPDA -րK"6*x4I[s=jTӾ0։ջV`*ԶH:.n3.ȃp,چ$^^Z͵oYit~FqAY2uqt@ ku] }qn$Lun=N.'h,z]9er~#hD1^\zs[bc]N>.M]LYӐ+]kzXӵR"액n;q}\ 2 Uq#?C*dAnlPs۵Jӳ~HX=h68~8Nm>_,=uێ>+_>[䖒H,N~fƾ.}yګLWsϷa[eU*D)l>"VGGHTʑ 5i %H*Ҳ3*\zI6 N- jZ޵+(]f:Uд3U"Z*O'ʴdTn9sX*$vMI/0xWڐx?5SkWq{n|՝ D"7Hx>'^(yx<֮ظ EbPaVZM;< f\ U &YL*ېɢCnܜN`,Xyq=ɮŕ ݊/ j,YUk.iT"IUv/-Њ#58 lcߏޕtŃ'˾kRm8 >GZ.^'w|F.n~crn*r>> GJR`J ń@TP8# L0'ڰMn5 ­ugtP^bŰS j[%ɐ3EkqA\c>1#DE0: @^h"s?0ёNOSLb-p"zȊ`'{VbDwՋv6]`ERCy*A=&ɿhfjTjzTDU_k:sv~k:O2((Gz#[tBWuA,Gnb/bO; 7kJsRڨ@E4ϔvM7#&iLpOk] =U ;5BPo!HՍs(d,X;Ѳ5 tʀKz۹ݻbIa9uY-U!0ԗ! Cձ\ݴ9y!^_?x:sι~nm{$}ke)9"G7\w,̟SKXu md ڿ]Jv4ʶ=xl)FAcS1'z 1Ҽ8j ɮ5jI5n/k4*j{W&`W^^fRRĜdњ9%HEh7^XV4׶ t,~&zV ȉ(_a я2n|9{bk~ƈךuJ-A$/,X@eRF+'qˍ}w@Wǚyycj"q kL]UjV"+cLn3zH޲3g[^z f#;q-a<7WM`TXfcҧZn] `w&k> rAqZ6<d~Ps;d,gqP/A=$}jBviThwh8sl`?UKkذk5J\[]*_;}51&g;NSW,73cQۚƒ'qhl{xjX҈|D<#/!H]̏ JD(h@.3[,}QTul,C8c.AyU?QMmh$ԸX{{T 8ӱrH"iA[1K^U~$z)};iնA"'91X3 jC{fͱbP =ڈJ$A֌"@$sUR-&*@nBvB^BvΨ-j9V.HG$  Ipv8"mlJ^0~ e[+qI8fH>vvlȒ~q?NYx/oK= ϿJa.?A-Yބ$ɟck|ϑuii"?5iV"h}u'N=(<a F Zg+ǽsK3uK`w:z˳ŎYYu5'8 K`Z dTǝOKk*GcN~LkȾ&ٵ^vb7F9?~i_'']]oQ VOK|5wutoc5m_^O8x>dfk#^pĨMdk z`I~ՠw}u 8Qӎ:}|[R1'ު&z:@Ettg"JckF]PĞ g۵ZTV {Б6sz4K@@1*9P&>g̷M|o*[arG@*omd 4Zݵ?4[GAјha" j$kLWZ@MIؠwUF 1hE-h# ۀQqRZcF;Q;RSA&@V1(JtJͤ7qiZ3qҶ1fyF"W\E @Q-=zGiMiX*6έ(DHJŔvSNH3Vm ,L֚҄`<T]s *T^`ù]7ƮB11˨_WVV&z1]H붘2YgKCMKgM{A]. GWRXZRwZ}nXM6NZ 1X`3#i3Ċ'mkRuϨmñ`8Pm*NxƵmV%OkZ}ֹhdwͯ!6&9=5p.q#5M#4c\$HN'4j{ ᢁTLcfǽi>Ѷ3ReLRHZh (JJbsF z@G1@[a9i|=DQZ$3&u}jU?5zO:}Ju\֕J1U 6]dKס M ǩz>=gI`n潑©YbjS]ZP5VzCry?G7_BZmU<=띫w!I5˵s~پ' P=DW4`^.t_k#*롹nZ"Ans91ңv 0Ffܦ0ёT,1Ҙ '46LNkPH2=1"AƁ8aTAjœu UM(23I$F #A6r%aԕD ,ga FF~ɽrc3\\ωY5{FUY FHc o # h:"G3U|DYp q?MY,G~1~=debܓk^K:ǻ̷[-zj_,wBKXe'wM.jzswW]nڥy^!sPD73]qxƠS Aq10zI"D8GS[ ⵺$F[.Lf({G+w ܘ'(Ӥ^Gr{? ("fh:<ն2BWmH=yWbn-@|$|#^I]`?ԟµ:E-4Pq0zɽmg`Rx9Vн FG7Yd2D`s1rzW u ٬r+d}~jz[6gCx0 j]cV-!!}mu}HǞ8^H't`D Oڱ״x~XP =*\z) >v?&έYV#>ƏX lg -[Wl}22j}wwsèu z͛ [x!b3Xv_u#g5:C'{8=nbw zGO#i=ȓvnf0ޭu/l٪Rk-x4nu`g↧+j"+aSީ5VUֈRˌQè׫!&7Qvg3֎*ߎ+u,{jb Q,d)x˛.wDC]:vqӞ*S|:ET'T>r^Eֶ;:X ˡ@Q8J@VqUDت >)R =Q``*ܪ%t"רH[#e].d +..z9X(D\ESdTm0b {W*_Y>޶XR&}_Ꮖ6DF yn`NTE+$@+̴Ҧ9=m&Ab"kzwVV(wԳap#5Z5_~?⯊:.,#0:WorWjcwOR i[k1s?ֶDZmK20|n"h7frC`5ջ6ۊ,zv@)jȶ5*]  Gz7PJF&UfxqʨZTMJ*J1:G6~$jV}ېkH `jP64ޫSd#ڵm=CE~Q ,rjVm d1ɃҊBҡiIzјusPĖ'ѫ)n44}NHZhk;gښ1M5tEs$sRbյ@ѣ=:T讪a@MI&:Un*lpX448JK uR-ٷԜ,+;qKd['t5 p(./'>VQe"0;TwvN;j}RHߗ^y&]bz-kKIOw*}PMt+LX64nf: &XIƮ: P!p`Hq\z* ¹d5STow%1-#޷[%&$x%EQcyfrzT( 9Y 09nzA沴Q}4;OT+Avq2:s7ST{|gO泃;d<3 uݺ=<~+ַDYϽhfrc}4E{4BYkb7Lm ""%8TE =2}WjSF@[8 &rkE 4Ht8 f&*=CϽ[^0JVތod޷X 䕟zh6[AeC$Vkp+MNkv=> ߊhw[Q% {4ΪXku+Z=b!c5ZƮNB c.9Rjn^] U;Vn9/m>ݜON/Um9?ڭ~\+}G5m $nkPvCLf9-EᄓҵǦoYm&fdj=h檈QЋل*(މB(FWX9ݸ/CXk0eH1'T9W }u  "cG= m:RZѥl^D7@+1?R^Cf gPq3= h^bVNMTlK$wğ+:XZhGLEx)BIUq⦼= zڲF9oovnDGqXpr9%Y$s=3Ҷ5gki}mC>jH=edINz~qVST ȫ$AQ' $Ͽ4ֵgU4G &U&9<*6~hYB73G&`Q_\ r!+q+ S+EڝOȤjc#牥uhI#tϷg[Twu.,RѢ{Ms})W/,*7 > /e@kFzM;0keCuf-d?9k˼kܷqQʫ\E$ws\hֶ}"$?԰3gm#QaB=cn癮KaԟN~V oN̘,T3N>뗒xSZj)^_+VzvڤN8!<n8Tqz u"pMGK_OUW7yc^k][pA\AMwMm󷈟g=+#㎏mݷ >Zn5$^<b~}nmAR\LכoǓKtپh̞ɯoOjW:Mqz}xWq@ִ0K3{T,MCA;`sVWpDUԗs\W^k(kqiUPжB!sh"/F@YV W~՘H "е;Ig#dk`3s]"+6WIJ Z:H[$957DMI!gNjL !(UY\PJ3&`QZIZMѫj&+V =T 1#zZx)9׵`R!sEP9d&Mq)#Ojӭ'z$ȠLmrzi)"ֲ aD=-A0_Q?nxq@ko34KH[ZKv'OM`YK+yy]b潑ê/ fhDco+6tPht[ Wjr\zuGx8渺/؛N}W5F R!˙k]<Vt]ik;`z`:F'oKm^&"έ "Gz n4=뮸VpqX|ic31s^7^ϵyW:'yf;D~_weϤ⍄Lѥ )01Ml9NFh'l1a ,CL& 0dPњ6VL" (UDcNUn˃\zŷwyD'j0{׬3 #8:w0xjf.Ć19.  1|8Ʈ4Pb J+տA~@Jm9Mc  6.nh u}rۚ{Ł$Gs55~G=uȓ={71dRcJ!LnAڳѝz[IR3ڌ-05;2 PCau2`veHLSh5weZue'[Ӊ{Bq6*AFUq]wz>a`9< d|//?]5,I_ Zz%_Zm[NLTHfP=˖m#?ښ"%L4C@ZmpG&ASM:nVү3SL41?ڴ^}L9=VF ׷EochP+(z0^\=kXө筕1_y/]Im־195:zV6a5ͭWQyQ5x‘=<45B$1W^\zzش6CIU L*)iSG̾.`V9=mqxpF qgiCL >GJbsG(^VD Ih7&bNS+0D0HBu)嵶HU0?Sᦶ|P!Fg\G'ɿr*R ?{ךGGxX~׷f$vHwG$}uV礖Ijt;q<ⵖIVG3G*˼uH?5iRQ{ "Ihb'FӀG=ElAʶŀ]d2Q6][eX0?5ʽz"<G^wtVv5);Ez'?Z;YP#]0#;~ly" 㻶;P%ʼn+Ҳn\i-t.=Wk(T %Lu^Nu]ސ8<1S^>ޝ`lyry.ŋ-g[={l[毮t)o_r̬ǛX SamT,s;5^V\-Nޤ2`T@2b(ZKډ8K.AzѢ]w1ѕF\RwG7[wO[I[,A\Z- ѷsy2q+`3Qוm5eH끊h|]ȟr?oM{xwQ rTw+ꬂx. BzQ%{G.pG ޖ;Dbx"zDG*1[5|"Ou'M߷`> V$c9ԫbն8Dj+q m%W~u^3bOO~ƦGJ,vE`w&Y7{ /=*=jG9ч5oGha7K7hU t&zsμ_Eqy<.=ï5 {ון/F E`'{u'%1:q \{pυ_?/4;bB5K^|29mf?-˯mH$"cSyo|jbQPXb"OrNbǍ ;kd4g$3O9/m׿LI3 sz|]{9۞ o@KtML7Q雭 A;1>X"VRB W"HÞgV=6gXvdW7%N Ͻ\rjsN:˿{u14Lnn& Ɲm9[WkN?ОȌt*~p9[D HHW RUU@:*ڭ̤73T3eY6LiZ<*WP`{Q4TgTfzvĎMP0W{Fߨ@S[[֣H`$ֱkĥWMeQjSkPnt0@؊Aہ], -K ޻*ivYɜWXō-q\@<(>L@6Kp"5qn3^<kN66niSU pab#9gޘ.-HҵεMTs+(UYA+QcfŦ9A%mݸ0c޾w#ֶRKL@]{W80g\,z07 M@4i<~(&O@r80n{:N;PL!Ҷ22zҌ 7Qn[%m7$E,nP*O0rޤrcąK/Bg8c?z5wR hPks]k8Z+bLڎuM :#h%TcԞ?C//@.+\&6k./XnW<o݁9;3+&)úNOj 3R}ʒ1CD7|YO=1-*4Et,A95[Q {YI-O~sB i2ÎB͆LZs@eASnVO(ۺLsrMݷ~y=zUJwO:W8cX ǯ_ub/e_$ʞWVAq@0W>@Қ ^)e#K™s@[:Uxgd!hٕv=VDE6A5ercچO7Qf,Z `@-Z]Ҳ\@1f{[$0/M[EچNz9A7#;(5X$j7\5^u2`WO` چ#sx:uuKgzTkTJݒxMr*\aۊ^E|ݗhyӊ˓|UjǓ»ˊ8Rq=EE|k +cܻ@]`OsۚWRNXv{ q =10/zMRqE LҪc􊎭֦3sTbk, }pEe9-1νSyòBk_cNh*l[<ZcrZ>KONꪅIo'3cW8Lj+i D`f{`RGTu%u0{WHU_Rd@ ڪ6 02,O~>MYj"K.Р+q mwr&D;o{}>IƮy -5ҷ bO<)r<8S1ҧ~{Xe%"GSz΅T+10~*e0dL"kk)۸ Uwr+ߧ:A#֫GI- ]r2 zELly\D`$קY?މ zgMĞg;7UyV|@u.Qs_Rm戝ʹ.Sϣ͝Zpx=>ǻѧձڡČҾu#ZaGɎ;Vg?jM` ntThni?XcZLHZZ>p:T([5kyk˗U59VjϽuTz jT5 XO^j-bP塌s姧SF~AeQ$?N( l.5*C'wZ `TB۲Ohypgh%TOY($( >zF+4 楸%=_H$֬ZG#F4,' ǞJ[Ӗ1YHi:ViM>LVk 4JA m0;P?:UDw!V]s%ls]r=x^\j H'+hVOsڻG6[ֱxz#itPeOVG2qQ]"*tåѳ\!UMq (3qV%RsS]/~kXZk,LӰʯ2O *pڸEU3݇c W4#1B#޲cN̒+kOJjj!}SyM dKq_6^G;)mmW99`|`b#VΎPdWOa-VS 56 Lnɱxl~ӑi#e0u[TFTafn9\j4,qDtIe%{њ!V8INګ f"Z$n3XYWLEz5@SǸs=pbe²Up^ aQcbjՆY2:RUmیON,vc${-{nSOh-w.12$Lߚ4ȉjht='ZkAu;HDebK:k#tp&LT:m%v:{DBhІǎjA-1?|.7Nӑ~Mtk! TbP"'ȬKlz18~;jsPFf̞|o}ָMu沓sO}(0:Ժ"@&1PP=ٞ9_#@[Hh#s(!(.ȷ50WO5@U\I&{*Q4pE%D QmCdk_u,e'1S+>F0$eu[eN0E\xƳ#O1yFӭ*[>`Ax+޿{QIޤ&$H?o&Cwo1ɿOğ51J5nAjzb 71Pi*=3F BH5\)үQAQfRH֚HAߚygr ZرkWG#i9Ao1 p`fn¬AN~QZ56b}D||"Z7IVHOdN+]ndh-IVq3Zlo0+zj^ Q GMWztV>ت`Ӟ{MuJi͠F~#^ku85䫶|$Z^#Epl1a.-Yk0?,]sn L+R[dz⦤ 1Yq8@j?j9~i "Hxɢ2O5}C)N*YE0u^؀&=r{U uc#mQzRn0~/S GkQ|]dǏx-if\3ۃ翷`~s[m$ӵZY/9-9Ejx3)GPnGVD.`3։rG~( .&bE= rӝ~EJ#5ĭZ۠5,׷K~̥d 7?ȚG^m%0X5NO]۞]QʸowkfЏ)5=__A|GQin35)󷺲b3i7Gڪ5D(n A=êzt,rdg8/Of[<`Kry8=3S^n7QV r1'17]UBl9[叮,jICt'?[2: Wwo{0jj˻"zR iN+_W؞N#n>1fգ6yMK23\qQ[E`I` b$Ԇ`K^y"ŶOjkLM\I4ղ`ښ `Lm_=,!hkMLzV #E,[=(8i' w4E*WnV hIc'hTY5X遀gi5M[z;kmM7}EF$\qڱIF8$P= D[S#l;ʽZ6`AiUcfIp/H`X;!?m}\v5$-HGJc`n2:Uc5qϸZŅ "y@AbClLJH* Rt'*z{WoÈBU H&3PmH< j&J$1ZYg_f*V`tN+V 񟘩BQ1$ b^R#O1]"zMwMZzHjT<>%1JH'1UH :jX9=+aQjطXrGor_O9М D*764s+W/A㚖?⚖7㙞ccĬK$޸:?5&U >kngⵣmx׮+3SbN$*tݞ$,s4lH`'4Vbdw4a?DBUv;x@G*P чW?MO= lNv^R PLQP!nsz؛]vӳa]E~m@G=g_y=ES[ HIj]7Ű; k}nҍ=s啓`Gk#|,ӅS[k#a-a_;_\ܿv8-~M$sRL8l1d􀤷67IH$0Dނ6_iD|p kg7n5RnʴT#Za7&'#mgZ"T@vh-r ]"(&l1Okqf_G`&k >H[_S~:k9+u4_=n ZJ#nGzuێV 2)f) OaAgO{j.r{ ښ%M_WG2qMM_ !p hkT\xY0n5ӱ_[2d}E_ԠCA+1t'ޢ"|&+z+a.PzW9zk];rذG\W MfeU߃zB1jjlfiVJJb]"Un1+bjҫ}~Q΂#0THwQ!f "=yelm{'΢ٰqIj9kᕴT9n2r?څzX?UOwq֯]nXđxt">H>1zA<\Nk[iE+> zkce sVgV8 93B"Z_F&Ut1 |M.n9N&9#I:ν?[En*.q&;QçkBm$ 9=ơbG?~?\[\ ?_>5wݲ. ?\_nU+h&8^% kqrm߱}OB$NBAc?y>yqԂ$:I[QBL3a[:GO\|u䲮@sVOSP-[yc^ٿZxW;{q*7n##橞Lܒ@ Q8A*AFb74&QӯҘWd*zaxɈr>@1Guuj bF}BN)WZkj^Zk jkkYNccsԩ'h Ltz=GsJ;'V q[kuFoQf\5 QT5hUK:gXIh1pGS=Me6Tn":[k_-qJ s#ZEu Qzo[McKs15Hޢt/T1ڧ-} KNh5>i?P >*/I4`s؋z? orDT^i?)zKc}Gs/}AWK5MC"Ԓ ?Djb.Dzm=Yk6ln4"x}kƎI}U\C%3]&Y O3]g?VŤFU PƏo;mB ܪ'Uh$G&?lNoP^Ս`w5&*l?aYc~#6N늜exOk:t=U}pw8qz#?o|WQp;Wk_%]~9x /$p'5qo-'ۚu'vsה+NOrsV6Ĩ(%[3`{ [=k 3 'kcoeb9f c]yrSa@8}ùI#ʨ_*${G+UHPdɃTZYVތGy>Ԧ !j#'u jh-Bx&b,ZM#MZ"[Dݿ1{ԇkEwh@< A *@ۥiJh,Yaڲ 0l$ѸMr13kd14e`"0y + +`b`AR& N81+M,.nL|Iz4k0ꉚ e6έ{Egs86Ǝ(yqiP5&q\\Y!⡩61ڂ*APA"MM W~=] oLnST\رV]ԷMϪT3i'`cڙ\eUqڭ vR-n&ba}뤎v<_^IrI$imq9 nA']s+_sq+1G*Ԉs#-:p 85c_);_SFPJػv\I ]\ \k\s\!f[5κD]:Xm'[ eYEtmAaW0d{7g HBN-bbzz7nXdki~K޶1ǔ;'^y:X+ݬ3+05O_䵴_FۄLc]LFIǨ:e4f'W+ˬ_.p9]@ EyɨIAcQNƘZi Dc5r(0 cSM97)P&.yiyPdĤl 1j -yq[6A'֯3L~xrń?Ehi}!IN`zS72zS[k4. cҳe>[c&ZVluV:Aز49XQ\ $(⭘%6#ܦAgb]1sJ9t-]ɹIVxncN-r;{(=@ A5q5nǙ2J9tmt~pm8 ~McbΨK 4n3=+T?56A$W9Z,y'nᘯ/>(/չfO9YPz=0"E1RJ n.$Ȋ\ւ@6 JE31PJi9 xIÂ˂A g~V’VA[;t Aނն҉kEH'>G;x,a)Wh؈b. G+UYm[`Ve͕}%{Y*T> Oq4y,;5ʏNҐ7G2n9H5~U}υ_ ss>+w\  /aPhZVu p*gr M ;hnQmu40鈣h̿0 Ñuq?eVN~;-Y;LcA5*j]D\z3ơǤ%gU3)&8G:XtU3l0FgڽVR/0x ~+a`u_S~+0jLm?ڪ%U5u*` q=VăwRvZ='$VkJ繞L;][y&@9'f5E-I㈊ߘɪfqFbkwISS7 Nc5ѹ<]$sml?ڲ9ЛW &EUM#O{s3'3^ݶ[>s_>3k]YJ75l_ֱ8bH +zo?M.Tș#@K/ӟh/@oX67^?K*ے'O3UE[&p^ju@vmk$X}Am#@&OBbPGRkLDU{OJZD}ꐯqv&thj㉢*m[x5(< b+~ۻf'bW t,YAp\PrLUH^Sb"j׊#Sϧv:zgzcioYPJUT}S5y>Y[üST Pf9qnnUe#a Va ִ2 Tfrdֵ e"5yU wnz#-B#)?- ʛ4!HkQ\lSkܾ aZT'ژXl$~Z^xڱ GogxOjWq̓&y⭽1k˨RKc[Cy$ѵRrScAinjDڧ+־Ԕڸa#j^~6-iBFG&gYvXk`Jim3@ּo[v@`t^/e\epUGNYi%?5QM щ i&&@g昅uF1LFi}Qi YqHky[nk1Ŋf)[b4sKwAK.IS^>=Xp ?Iju 7EفV=1zΩ41|d{p] ֧[Z_~3k:H=jHM&GNibZ_nV`>j/Nv/wlK$7޹^ձe/*I|f^m֔nAQ5>>ng_sVCS!J V7U\;+0GWvBwHzڥv]@Mم &~^UG-uN^V N=l^~ǰ9 *F\hFN+<]y YnݙZB &k4 9Q1z><7kjMuݹ$GzZHDĂusYR‚ʦ?VG߽tZ%Ϥtf"@az ' XUQT'˘ {Q#[i^2I+9_5]z0g[c}& zW_}c?z\M|ۏnEg՛JYz笭g@ !ݘk ;Ԩp+s>H ⵊ,7{QKv-EOHbڝ)c1UJ^ph_ޮ9uz158Z>[]㍬]ٙ58mҥЮ'0ߝqv4 +E 3q%lH9 cJ e܈HT=hvT; -٬T[A$m38mYiT6k$tD+`&XspHމ^Ap9ƚ,ZYMb 5[3p+DoC3@I1j4kpb t* c"D i {Š-Ӟt g5jФbN?t=ɝVKhl>梭nW:7 w0df4YX:A5b*A쿘p9cu!G5eJ cJ`, ]e]yF&$GY'fV2xUFj;Xj( xU/ۏ`+s &G*|SZ731&989WR/#sgcD^ks5[Q9Z7- b:~+qî('E&jbyn:,{U#m]–54ʰ#W qW:T9t] TUfSZF#b)dNE hЍI P.>ѣXAGZ"O0gmxQ=KۀKOo&bAq}ߌ!B~Wʫwo **jdeOaՓWNp;½I$Eq7~| iaG?ZJTZ?Q\(&, zXӕV1g&ZڳվȮk+g,Ɯl#XwmzEV3W< HoqxS;xUHF[}j-֞M}C{WֱDl\94\xgI6{+"3ߏ]Y"Ak>OYv '~)#ǓU1'<C1rZ\~h2ZyL4Tl`ޚ&nhbܶ$[ON`> S?_Rn, 'Ȋnb$WNDw1ounPqV^ŻfFݱvo8׽|_uF[l0T GJO_ȝxi?mGg+T&zO@\(j{'j^`b=UjFb$EN\S=Z@Y3!dTU ӛבWF¢q}A1U#{GӺִ@3{IsjοkNaF~׍ur5ƒEs1ovV42 ce©Ҋj-*7 GA ۜ:)ikZ(EFSrޛjCzyCHV!A2{V[xUxЃ2~+'>v}7}B81yuq﬏?ztV`{צx3'U- LyufA;s'D$DիNh,-=OSU"(w ls-0Hr' ⭚SMf5 GNr1x-9Rםx8pX' rǎ628'gomnT׮;2@_ }}+YmjAvު9^ĈֻG~ۺ +n' WHE%ӊM $xE=$k1~Θ" =Xv035D=\]#PUע8VFݓƳ."gHξ5΅r$}q)X?2v; Y6E(\Xs,ǵp^Wmk T$ lāUVBd8P L@FmzP:F$Gj H={(\L@n $Qױի`tT[k~x]ۈ93׭eT Ѹ{DdK~($f#("Nk4_ #dqZݓÀ shhaڲ.@CMsVWq,2y5 ݥq,5mm AX;"YF#4y*8-ƞ׬CPm.MT8 {VAmh%I x)Ýߧչ%p8* f5xY^#tNMvιԸݸpzy-QdlӚsLz+UdDf O$'Ho: ORqAMq:W:4{RѶ0sSE.H8D4*l$ q\i۸nƻC^ l luUaXK,w TMHoJҢb%T$yV) fj*Hɠ9ԉ{z?TMqRame7~y:f_S6aur8xƖ쭱$3]yW晔7 ޺8ҷTfb1t;SK z}Z GH\: ԀH=Uq-ôyq Z6?>=|ǃ2[@?j_&54^K2D9~=L0qrSGTUs&d_ez?FNc5xg{^[}tzO û ڽ|iʽ6\Vߨf:}U) ?զLHSҾ~s䵚yzڼR:4d 5'v"x=jcHh("zZyva+3k%[eCqO4 kxڸPE".]He U 扱T[Z궡5"Gm@q%:aā<T[ܺQIs^?<[/B['Unnf |^m#09<|ת8Wng`5'޺J5ES 5Pd bKFGQMմ({2i-5-&`hњ˪U5zKv7>;s%'*O"bɩg\]X"ml蜸^F'aں^QZsn֣- FfckZ!?\oLjYj0J1'\\>I`&nk*w%vt ,JayyuHD lU$ĚؖŵURDr{XYob.ʓWĀ1 @Զٜ'ZܙhVjZ>hQ9׫lY%[G_trGUfz<0y#Z"+.&sk*[lL=5d`q֪MxOÑ;ZC=:ח6=z|߁ mBx1ߤbesָ}0OzثY!F3n!u&;QrDpyڪ.9ڈ@jW}HcWH-Fc/ީ:)t OCҫoLת)U#:>)]vɹv@֖vPz$qBa*\5Vܬ-"FM O7U +m0Lr=']}6/0b:{|?봿J`A@מ\t/z-ncШu|/jSV?.&ޛ"=ޣٵvׇ*010>*oH{d@#ocYze{Bqss[*p:Q K ڡ{ӡӭ$M+U 't=GSzQ#Ngۏݿm wm@5^j@6T\T.4L|<*i'a_j:HxA.NOK*3k痻O#»6,w W's|__׍xjn\rbH|~}^y0VڹND,6FU;sU*fD ƹŷFbkm< gVcnƙ)#Ն tENA@Il饃:ʹ؊$t5xүr`Mz#Ӝ]*ßj#Xیijg-#9[5Ϋ*3F i9YR@ IFe 1E$沉C$`8,j#c`m&K-2*P4iiR,{h#.d9(&ԃ#ZhMt hf,HhMagFYDͲf5Ҫ?nhLP-7?z5zʥ{p1Ԁ LlV,)3K%:(ٞ:[|X` sPa}3Z)j-iɨP̬!AJR=Dڥ;'b}@ԮE-9Ҳѣ+QW#Bŵ//S*F~i*2?zm Z x[Eh2WWеdC7U;A ]dss5^Zz3`Wi Ap#] vg_R,rg]XڗWHvtJsރAiL`wu+޹hJ]"Mx{*$"s\h{Aq ڹE ڥЍHL㊅- *?8T'VUٶF@FkpFE P;zeoI$v4 @ Yso)6A9{|zbӷǙ_ָomſr^ks#^uw@;f] Br:׫ܶpБ5:m*X9GϷ6+`t;9y˔>GJ9q:csԀ"5%ҋ]1lu[+i q_EFM* @P'5>CYs^jX䱓T a?x#v yV_ֶK0?*qѷ. aQokI%ϵoK'-wQ<澟>9'u<@qQmy}97,IŌ["V1BtAofjyTBϥ{dPhl"lI(h{8ҡGYKj9,q1l-j0?qzš qT5 O"")ZV:ԥ;m ,5ʰ:Fb]$Kw bMrAn$.G'47ew${Ѥo,#VB3ҭ`O~"I Ύ⪉[PuCp#T 7(=8K?[.;$qfjacaARc?OW}ypG|/=~ajMxb^wUYu2(苄ֲOy3z]D@/ڂ`1{"߫ւV NҀ(J v,@Dڬ!II[659?]E8 tS;=!Kn2&3jy<9z_!vڴg߭~ŵ3% ^Qպ^qaq3]ٍU@J.s5cz&\ N6.s:VVb@&3KcJƍH * v<`tsn.Vp3FǼD_^*}"s]C1Qoa$I8ϵzx;I{dyznPA8c+۶AS[:kir+#חэO9:.OiOI9#>^Wt83w*/-7D7BD}z*U{~?4pT'k3.jէrgNJQ>-&KXQj/,zX [WCX'yl~}i)BtK#|/;[#`I_nw̐^n{Rk̮ 'ejhukuH5uVrUW5"V콒wnFju]] UUY M[u‘ h'{'vG=h.逷$QQl4bƿin)Mz:kzmw1'пG\S#j5&DZ&l5W˰H^;㺳1}0ZD@POzcZd085 33ZXϨNբw= @,1x?,D\$ְ m l $L<=cJ W߯*Bys^J=oJo7L9ށiN1Z@OsXՍ&$YT"[n89;mP $W\ljUWgO5sƋXZߩ5JnCc]gWAw,< W+Uē5g1kq[,cUu\DRƈ޹+*m%L~j,sПnL_[UwR-ҾW^K}i_Sk%\+mTjmtǟjC_kI'4eTUI"?z:ͺV0pyt62R82` Ex$h2A2 5}gڳ@ XS:UH歪;EuƸ76Iӛ_!"d1?kq&Ev`q-U(ӂhz *˂p=4 Eb`kOnK@#ް[rp@ MI5KV=EBDZȕѩZ73f|F@֊ii2?R $P!6qobgN15~DIҊ39p\D|;`uvT)<Q[,`dbp pzu$[pҿ]#AoMrp3q =gܞrLwkj{%K'lEMZ TUE onݫk>HxTޒ"T[d֦gLOԭ%{>?;O>Lc_x$qڰo\#|Ux2H8=Zm sWXcF;^:yWwv\ ?zKt:/g_ӎIӏt[mdO^'+wrND'`IuBՕܢi,-˴+qrvzoH'&GַfJ"81[&QB aڀ>͜$X5]*8@"xG: =묎V{Hp7is.0W(][p**u!r@ISc?JqLEEw ndOڌ'wUDo@${PL^ h/I4҄Oz3-\*FV;2qU *`աmݽ$eOFWGU$G^4spb鰛T <:Sj2i▲~ܶa1wɏSG0g|ϠwT. ~55GG="ǖY5*;X"nwZ&/?z!NMM]wztZ&bDJ-)V5 t1@?([& wK353Un`~<S8Q]#[.^diG ==iר]tFMw 'o?" ^KW"asW)^!}A=Yۺ=7 Ͽ8XOdtRr0Zu=F1K#>mv$T.Fե LD!Iq9v ㏵uU[4O۹Ž?fW\#6HW.ZV.+b-M.C&guPֳA f}t/֡Qă\z+K{I_zwn /C_7>{LEnNAT"ErҦQOUjgQi" z-l>0*OpS"GY>Sn渵PSZ3)KZa9$؜yE5YYFOڽy?]xgO6Ӧo`Ϥ{ޞ?/^g q{?[]) 3^VD5qΫ^P~#zM3q^3Vbsu4"ł ^O~(ԘnôAKo3`<#Fnt8EzѺ=^բǻ}'7.Ц Zqi i_qrktt_nWx}?ڋpѻ>[Itij9O5r}E{8P7l-PJ3 YI ,s*:}O>vX[ձ]1ߚy~jZ뎘Z'k)&MeMl\g۰E=V›TΠzI51۞5x_к*oDrFkGx:u#A߱\o] Xn^<$l b+^mz8}0[h[5GtyV  bhtEeQm)'=gܸYނ>dVpDxʪjj-D  bI=z9?NsRל^z\T]$r=u\E v* Y[SLsDqކ+=$FbbſJ5:V)`(Ny,i&2fKBXEHCSqIF āFVlHɬۀ`YA8Ѹm j0;Gz=`I AZ>7#1nmjš Ș1$EyYZvY3R my#e|ԩfݝ5-2cKHc-J r5 Yp:B{;JDuiU빠k\k0V̚ջ{It&[x%+dHlÀ@4f&j"bz+Seܧ0Etm+GAuVԆuDW%p9#"+XMujkQ|`*Jz{7kI8: zb: m\v@ ʭnyC+tAkh[P= ry`}@~j*ٷ,bXt EMRzkf@Ԯ549jT?PdRwsFaz3P  FDb*PxڴYOX/ڂA<}ω#˗Wq~ߓ\ޥMڻ9K7b(Yomtb^e9i5t1h5X#r+כ1sVno,`}?yг l)i5&3TQvKsrN"Jv8u_޸ <ljuW#?mrki}Yci\Ӌ{z-e8B  DxhjKA+.T.gJlwԑxCVes QB&yT+u7n n#fu=\qzr+{HA15>=_)̺յ۷&1_ z91|13j]R2+Z͐Ƀ tQTmPzHr}#3]PgnbZWBg"Rsqk,zUF ]%N'23һk1t0`i [qDAѲ*_5zcn֥ `ĿRFk-$*tߦH3?)֬ڼ_N'UWrFkw~G| k]03\HCz&q{ XɁւEL4 fj} b;Q+R=`y;L իKÈE =QcҲYB 2:b0s3KPfꖁMew@/y]T03Wv͝:̞G9e ۲iSmܖ_+}t˧D ;5.@ڥB 9jAS03E HFfMfdP eӏzکQ5f(ޤ>Ʊ@$?nlw4Q5 ֘z*\nTQRMtv1K #wCOx !lb~k\A'Һ`#~s$|_B&r3_g_*ջ$fUox›BTڥ #S:(f_OjZ}n0aH3M` NsKDig '1[ z^ږDۻוTb OC9KQG/(9anظC?c5| 36kpf[*LZ=7/ -ua!Jt  gV'C Fŵ|7~wp CM|fZ˄U&bI$|ןՎKm]kL'y:W>swaϨd_Ԇ,w <*岤$j4ǺtKP%BBQCArsU?$n!B⿏N.?AnzE>?M&QyL` dO˕cDf.6\"?O⾟{~מ<)Y:+ۯ3n0},y7T:Of>9⏋8F,tbx7?z9H=& Vڸoz4o#'ʑDEv{ϩL{H^ݻ;{ܓX`(P$LVv d=(bE I2L{/ݏ }2s_뾹9.iELO-2s^H;=:޽~?yp)^g{czֽsO>sT&bDGkǖuθ^FmrkӺ=fj+(n6JՋ@I9y{(A"o5"%mP];O"O2}ڎnGecZx,gv~E#q# i0Hދś:p1=M *~:w &&LѕםLo`*-IuH/lVZԩciRu>և-$H>j^kw@}%M侸וl!ALI;VWn9Rht3NERQsAzU6Pφ݂|0$ ;W;NM )zxzZ|# 30 Bzג:s[&5͢was\uW"T\ K($~ٮ=wW?WWkh0ViUdk) Nd}jY,/$ ?XkvQڍupZtZ57 =:@FJ-[BC nuݰ(?MW+E ]'o졢9czW_E-OnoOJG;So+Ձ*(ձr1B;}@/$U5 I_+l3LMAm J+^2'J$pcn&OZcずioXiNDjOA%I<>zsQC[$WAoKa"򬬑s:+\`+5OX8?ZV &kfo01]ҍ J*ts=8a2y 3,FXbhD5J,wqEA-OfE>-MInjA-J{PYG`HhdCs+:GR-d"+(=(Ԑ@oɠ3$CVPcSAQH.QYkq^g+ @e 4@ީ"3j *d~Imq=e%@$ԩoLwDw<Ew-=hb"$KJ&bQi2~+\\VU^&z(;#5Ϊr۱Ʀ!op$;ԩ{Kl7Q]Z&F6$ :Ե5bO uʴD.QeN<թ"xE,G;TlI'8묈+FbD޺Hk=S-zGO">O]"W &߃hXG5D9K,j=$UL 2? A0 M# YD5ʺ4:w5m |\:thU.\ n+up;o3 R)}ubYv :(=[rjUYp'D,SU.8ihw#oHbK߿~~sWWZG8~GìM]pfdv1Yc@čZ@BO^;hfT]yE-x"+o7\4Lj`4m=xc[FHyO~׊rkRnJCOyj.YtFwߚ 怸p tu8^~-MӃl}or&xlh~酹sE#aK ܏ϓNNj/*Da]\_A?Z*:_qK_B;$sW/^ok֐c;whz~JF񈙓ڽw+~Z\w!2TFm]̏]mhfRc_b̠c<7oq3o*ݻ}>nsxԸN'2#^:ܛj[(v #rqAdrCS@B Z3:[`~ 0֍(ɕk~/Sect+ߺR}zM FPY"^m Ͱ@F~#TT C58"֘'ohݓ`?iCTJdJr(\d(oA@7jF䃊MOcQLqZ`xInWo7?CZͲ9cW<枱DA9'TM_zqɝj%DVn]Iq,}@q[-ܑ~PntM6X M+[dAV.ڣY"WtѦy<޼L_hy2P= Ĝm) QZs\jV#ˑ! P䋁 t͎]bv|K/U4 A p{_ @[3zU@}Iې~k[uOEȎ';wTzM7Y>uu!LF}0zHRg'Mi,Ҿ-#/nS^HM0 iO&>)_: :dWma'p)#WIZ?>VG}G:nSfW}K ڪg x|#꠩11'<^_g.S֡!a 61rvb"c5)N Ҹƹh̰IQZ`.KdvԊvb:ւ++q;]^T@5۱9nilBo.%5>m N Z/?KƘ@ɨZﭼJľL@QU++HOz2$VE۰6$sWtq[3Vش\j 7rAE6\6捈P!L6/* g#JUfZ<{|Ymr#cq'2?v»3I|Wyi[3HC#tsW7{HjYĴGj sVI`g.XR=f8V+HTHƈjp FඐA bI T5mgbl )j1Qڍv$1֍En9CP>TcKpNGnڳTjՀ)uH2'9Y?҂7Q"*qkq9%@R=D@T@$ rB$hiYʅDkt=rV-ڴV2{Tq-f*l:߭Eh@a@R nsՕlXR|V=F=1ӽET[%R*qMM= 5 6Ț%WR dh jM6RK'kKjPBuE\#lkFN⛄ É]dF_Vq<9v}I2v,Sy~1CQ-ubk|s]bUbb1vuqX'in#`W޹hQjktzc Z:W*趻@V;m.I=5çX AĎAq4whErl7j渧vbJn4m e\\`z֭9T&E{2 EF:D41V3W ~12@=dz3]@yW~>Wx*;IT]Z~&~|pݷ !UV+X&a ^ן5?[b3k//~5lhj"I'jx"JޟGoꯈj]p^g'x~?3w1+DA= d1 OڂNV@h8 h޷C kCDA%Zbj ;3z.˘rv[}i^?&XV83։ZbkOEb];U;^ҐB 33WV `ʹ9ju;oV5 ;wyz3kQ I>oOx<<؊׭{MyߊE:.zScSicֶa:|z< j(f Elnҁz EJ";-ɒ#ED[y$LFs`j+m8]LF(C' V]/bq#Xc3Yvdov=+\lpRYkiq1 k3ǑI+=+/{f6Ti8'z#\mFk'-Z]y =leBͶ6FXV08H:ӆ~z1e|FrA ȬoEʩK>">o7P-wOvwgz.$1ڸ,ڏK&AM=@odW?WW`Sk8%w=gUƳָ6*zԒ 13OM o̓*X9xa<3VA?cQZ7$Ny*YOgp6G1JY aEh`2A &W5qNVk7dD1Sh%.c̏Fcgڏ;'1__إxφVb1[,OiV䎜3]5^ŷ}C2]!c~BC3uyz!x<=1M!  zp9/H`?z+Qj,N'=UW 1u;T,}?StMMy& k> 4zv[yFcڶVc~ `E\ǧ?qvUDFc'٘ #YcWH qҪTc[NNGNk=%o[Q#"_vu׌kp鞕#NǾZֶ$γո۹p/"KjbҢg9Kܛ`cs[ꕭkڹTj\mc\aG)^Pz*6C@ mBme)ҳ'iӀKL0ZVp$ J& <hQcF}-,䂄Oh_M[i.9 r 87qW޽/-UUO*2f]>Ƶ/%:ۆDpki5BҿyTD{T.d/oz46 Mb9!K\Q'A+J {Zm2===YEX &B=} >l3[@{~qTaŤ<30gcF RVhLyh.[ZkpBs5*3Z` 1~͂Y״j!M^[嶕Cڹf$=l(=q4PX":5Xh\70p @bH%B6{ѶZwq&kShC5Xj֟Oq0m+qnBj넮q]$s3چI'\ w^DuoNEt:w{WhV^ks[ƺA*dW56QԪ,i@Y$ ,޷ً6=iYb+AgSڧLQ$ oo-Kz5@ݸڶvy@\dbCkzV!ĩ5~yyzXuYOj"+m}My}jǍ]-v $錯ӟ9*8]XZ s2rjUG3WX*]}h+;v|QZٗP:I~,j-lDUl5t K/;W:սIRַNRQO4k7Qkp[*a᠕̚Y*gYƔYS*)):mǴSLZ}hvȩXcT'޹u֮G/;xrOzfeAl85ӃBDc[9 U&J$Gz 9bVL{:ztH縠kV2hj^^4+ b7jIdQ)~5AuMnxC)m, yʽ[h h185J*X%ARW7?RT7T[`Aï_/_>Yn'ۚcsַ"nrV9yu+%[*Tmf#oYNvI4_{5´K ʑ#y7uVr5{Trӓ⼯.遶GjwFo*J3ElxoGdrLA' zt'CU4e-HCQmmێ ;O21G~@@ڎܖ]"k,IM4<@I#\L_@e&Gj\L-F96Ojzr2. m!VF{W?g+Do /n1CSIVr?`Gk8|'M~橼are%p]/O'vWj$Z<79jigFX=&xzn*W񰾭cWג0H'#*c槫Gy.<(zDfK̀\6U}Nڝ'"^, d;(cmsZߪp4IF05[lܬQ0Ojux/nʵu$q l^(Gfº/DUY]'":$'CDjU\dXHp-[edE]rW;"f+QU,0׭V#SC( +[ϐkb[HKiq"{99dhb93zG*}=ȭkHxs .ڂn=; t);/=\3+(E,GjFP.Iԫs$TME5֦DByʲ+-2y9+O:D }(J|8v;hOf#q{Wi*k)Q,'ⷎ+frV Q̙q_o9K.YH+'M|7/-t "fOaF~śus 0~MKcQq6W W{TJ[ j HJ GZ::zi.]#pAi0A V鬖c{Pc6ڶ7Bkc+*je^G:hsGN+rCčI{XN88Zv';zJcăyAq3TJf{gނ.D Xub *2;)bڝzN y_fzVV~͢sIRƝw֠Z S `*6ۃ,qSTv  ֝HtAS#; Qa[CA"MnkR*MNܵA";;0e#4̀ 644N&Y+HTUH Nnޜ N*5K.[uShh2k.XU"jW,[**uq<ʬ`<>Չھ{ Xs횴ڒ 1&6{U"=Q0sҫhص s+F '\K/v"\g7 ;ȇ1WKߊ ^z+ۭ2\#>)o | ZJ~9YqXxѾ]g3zW;;g   c1'\;̜B$0Oɮ; 570"Hj"9:2Y7!Fhyb'q TN1Q9>qoYMSDU鼒kQV[]Nk"A 'VQR5(|$sS^"bpX+,OjW}+(/Ճ+}Wkn[5џ*=:>*nN[J)]d=|7EͦQVo\0Ot;1tgKgxYG},p{JA-Gv=S醶71UMECͦHcڹklVb9Fn !nƦX9Q?ޮwQyh/2^<8uƷ4ض ׻߳8ulKQYv:[y_ ;rd'|ׇ}\^ުnpk9 R@bw|:f-p+?#i8?v᪋$hNrjW#]d&HkŽ2!NGft0}"8v wnɞM kࢫ~ OE;>fbz3Q{rE?],[Ox(?=Qzs֯ ܴrbZIb+K巐0Ou^5u@[]@jJ]J 3j[J$1SU9jT, _tQ:?1k%e|[꥿+z-;~1ZW%+ݟP0Oj]o!Cҷx嶀?P8٪&c/)|nqU}mfe^"gt';έHTl{˛9OԆf'5խ-.]C%ܼqMc Ppz Gj-Th"G*1p9#rNs]yeݶ]dq[/]dr;HM DfYn a`N%X"|d{P]9 n%)hҭ݇K`3\88E/iPGS=* S$zW 5 EmKſ({4U;VA9YEVQHfi`Hr0~Œ1YfaR=lh i65^iJr9Ջq856`6̆1iGcPձj["͛&Tj^m?u^ $D:Qh Aɬn+i6ՠ]go\UL&`T`i ~ERkSF'[V3Oj"5Vr%z޺D8}AkQ޺IJu71 cxڤ@ںH|KVۚHawhbI( 2A5nTtD`Hefl2¢:]`||fGI˺`5/Yb5m ="dkuQ}kuYTIP;U"ynAuLIj+N6d#{jI#sjYQme cbl(壤bVҦ 7Up 5@zLV^* $b>\ cy]Q;Z|ΕA3ƺ 5pLO5Z899j+LɦZ{[ڄZ1D 8c%N'iX[3kukNA`{kjL +,Nœԭط WYҡ`O1+u$YLMN-vySabn#1U*(v2H+nҹ\AUkpѐ.*ZU50|sF~1>:ϸU5!3tsW`X@xO1eplιsM\jbHWNULzN9N\=k;Cs"O,Gcjs^?gĝYT X2~n2W45xckXsf- A5>YR["ی&O\Z+R 5PvHdщ5Jӵ0?4HlѺBO`#9Z"b@' ri1@F$6h .{PHD@t"oa?Xn=;ADQ1͖V`j*w6IF`@Mt5kXWW*Ӽ̺r#Bo|@v85!v \ ${Kw7tS[kΗ%@+Zx g&4Q^ުIPnX#Ջ$'ފn ;sձ*zX[6dWXY~#|0I?ںc7A`B x|/hO5 &zf}ϵ~k'r-ʍڽߧUOCUtd*s /]E;DC4ȱpJj hY,桚nٷЃ5d*Қk*7#[6Uikmթm._N>kEj4! )XIhGLֱ5=9cBUu@ZZ3i bBh< E>u}MtVU¦ԯi :-7k꿟~Z.f/}C)BNٓ! Q_|\?;]|y#ُ a'|+jԃ"1^/'ʝg;>>7*iY`,f S^rB3+ƽ5SHn@@WN?L c@o%B38W$|P03"{Oi1onVIyη Ͻ\s&9ҋHSGx%FҲ8S[̢!5;]"9u7tś+=Zb[GM1bpAv1]ےeo8^Ӈ|{jgYltt.:v8>uzbA5c'Ζii?cklLUccݺTSbΚ[Y5nC_eZ 4Ym59nްiH*H'cEJx``>=tMD*D1h+sK H ?-Sġ,Ҥr#u#1ގuZļHXAVPI9-ٶg&c?(F[;zԒ5\u4ef}KZ?s-a YWPfz*. ގg{UNsC4vI&WPQi^>'@ uk^1!g\+e7_eW ATTr w7&E_.^Gڿv,dA^Wf&A5o 'ޟO_xnR %= |W?/o5Tb3#2%fMMfVQXjx [@",[<s?ŵp \`^oށ9<,t^RPK׭N贋fbD5`jEm]xFc&ҍy -Dӕ": Mu6xU$êɸ HltʄbԈ]c2 jh7.;GDi.J LqX&XdYmn"( 4P>PNEKbV)zQKJ32@3 ~JP+/G4C78X?~jh1R'x3 eDfXSE" ibŖ^X ɩ`77u(aūoĈbݵ-$sMf z6LV{RAaf{knY\KtmMJ-[ Jn,ApD{ڼ֔yI0>Z{2jmT sڢȷf"LJ6oN}!$ [#5 mީ5kId]PĚ;VB3$9U&p TsBxA|JҮDk;_TOR85r1x2ɶCW"\ωkQ]$X }뤃Wwi;O=Mu+y"S9"56*E8*LHm%&MFf sͷ I'+oL+t5מ/ؘ])\]XeM]$ Df·usj!~j+bsQZTG* ccbnA_LR@LWH*?bgIr=z/WTҞTQZ$mGf mR08'tT@z=x2;J(xj%n:h{V7oTet`RK+I1]q<8]i?58tʙ%W[ճiYֱs]{Gk6HrG-4lAwIQc^^QgUr$|Wtʕ ߭f {gx(RŵVO=)j1t8{Zs.FiP0Of Ȋh v}5_hklYQ$zX<,?V+bHi55H!gq&rSK P] u")eTIފ 82|V@hI"($. aEDדD pvH &0!єGZ1'Dl",J[ K jZ` ?h-޵νqq$}q{+8V:-m[hOKH3x3zTHl Ac.vlۺb5:eBk\ο]4^+ߎOgK=f[KpIsxrNޱPdD*`|D""> N‹PcM[z ⭂ڌC02hpIɤfbAiK]…as9k<(\XgHvO-cҊzZV-uZj(,gE=MjÄl{H.в1怎@ܣ-X\ޑ<Ѳ?N|WR-Q3QNf7X.1c=OxZkʍO'Sߋ^qٷ"}qbCW4ffk<&o#7A-3~jAʸ9v,uظ贗A;\v- yvyH+TX:-dS=@uNU{G6IhWǸxɏ'[v,Hڷuo:iE-'OL 'z9w޿gZ`{yz?eR6ku_OUPF}zCx.ޟҥ\SjM&ۋ۹܎:J/S(m=+֖}i"ݻV/ U¾KY- G-W;W)bҺfFGs.xj젓 * 3fUHtXԶT皵Hnٱda'[(]">+1x}Sn"aGiTs٘#u³֩꾷{} *L|N˻.?b 0yu*3okoj,N3bNwXRH:j ŭ& fcOWHӵTP0XV+jLIh瘭²I8n<8oOsSN7'&G%RڢY-0l|CXlxDg,y2?Wǵxp~_WPn8 Pƀ uP$`EMoO5Qj>>"~:muz-m$V7O4pю[ͨ1R?$t˔f{D՝=mr7WHG[D1tMU]v1:7 Kryuƹ5GbځϰT&䞼M\sЄ}9zu-(sUm3fYUh&l(]in Kb$5-JjVw='QPG $ei)E;:D$k*;J[{,PKA?ѧcY$AZ"1YU7 }Zl gQP@LM*.`皁rI82i,r; oO =h*i[Mf ּ T鈶zj}:fm*Meŋz-$}[p'5m :b j5Xr.VyViB9PȹmqZŻ@xAV4޺D3jJ?|U%QudESjOJZ&qȪrt6V9js2FG:s]N3[5&aGir+`g_tLzWYX:ۭqk_Q"y")?9؆]$Is}iqT.:ֲ%}+"أqĶg]?޸KX+"WHسjH5ʺH5UƺȲWr(UcڹU^n2;](*D~d3 / kil4T@c=T] uom M OK*0<<$㙞k]0dbk8"U橖"H< 1;| QQɭeaMeV4҅lZĖ'VEw@>Ƶ+a3l[Ђ&˶؈RV,.1@R]RڧZ-_OVI^_J ޚŋQ`=\FH4[w1+M6uߥz|uø|*~'{gӵx[* bVڛoh c\[$"ڿW#Sy qG=w!W]g &r%_96NQxDkiylX7+>$HSs7S#YrYUb91$~ڤWcg5dAdɠa zH&]3f! 2f!gYRt?5  J3Y- FEؑAUNxcjfOi@WfI.?4R{\ހUA#zZZZ"*M5hb 1<@IRIؚwtiUփ*hmAĀ:*yz2$'۠_J mT原S{r^uV`K/=50n9nC.{Վ!p-F:?c*23\ڸz^zI#n9r뗣<;ĝw?ǢWE*ycMr:=/\nۂ蒼jgD<]#Q-3Q0>ұh$9֝<jVB,%ځXyB 洽+j.dkq{/oPLD#IkѨ&Љ9Zj;usVR^t>W&q'{W^m w~9O Ic"D55C/fyrjfVG|:4(({=kb C(ڧR"QZWl,6Zt9hLcjWՋ mf&T"H2HY`vUj5A-'hAkEvXƟed<'CǐzgZI:817[#V "[hoZp=3vm++4tݶszF-[ rwbz^94G4j"^-jL s]xrxݶ^kb2"+ǂc.H뙯oO厦 bԫ /s^:0޶Vzou2ŬLÓ95qï+yl=)ep+Ǘ^J?Cٺ?LLxӴ0g\u=a;i[dg7^EgsO`f9rJӷe@ ڸ]%IorŮᅱZ09Sצ+Y{sv0 +勬=nI>[u=_$DT ;Q$ϽGz~'}UY5tN 5V뚇[`7OcBD:+<'4 *KrY{CDг?QXڋ ʫ3F-//1#uZշ P@ {R&EsKS(}KuуnUw,$ eg[kBnmbv X}sӇR,;W+1Kv=;V6XhWHX!ZW3]$sah9%Hh/-OnG;U/,esɯKH+sBcfD0#޺b5J֯hj3bmH1#>լ,"H"?el f #v| Bh$k;g d 5ӱduY{W+]cIV S\jkem]`grW=t5f}M+q5` lhi٘C[{dҊ]e* }+AŁAۅPyWA㺃j6Eu}~i; On+[|\$~yf79фkb{qT!$րݨp Ҁ{ cLaQԐOZ5OmLa4fHJ$K{\qր IX ҁ9;qZ!lA'mi{k}$>Ió0< wLֱbÛ_s{[ =w7-B"krA!/`AVZH<]ш!?jGxs&`LzC#[ :@oO6/5Wd{MsUKѴG\//W=+Y@gߊz.\D_[!'cyykҺ}1s\뫦۬2u7l_x vN4bI,gX*qZ6`=)F1ڱGFV*31b6!qL85r9}V>w%fF>+p+d\A$$}뤈v, Yz۟[.cu GHOڮŽ#kӝXXwsY>Ĺ؊f: G'=# j6֧RzZ I~Vw,D56'i5l7,N.bb3+4f"ח*1bYW*@pL{< kdUj^c'h\,'+u=Y2FIgcqڽ1TEz9ڣdሓwɓ 'o8huW޵Ӟ=]> ,03'5:֖Vk x;sSvsjl py?j$yGԿH[zmS'hyJj[SӚ~>|_7ޏ[Ep3@w5;+#nR]lm۸ҽU+6:[.J\l\AM`kQۚt.[@`zWx-M,9'\[ZoPOVkqI{`{{ٞw@%ͤ#4ocj>q+@&$y,\'qPn3=teGKR"@*ʶ("kQ~ſشΡѫĎs bX:k6Scu&FC/fjͣ֞v~^Eb̾Cx*^;@e@%G\UT8}wznn ;W*Y`C\k{#\ I#'sQƜmL J44ޠii(fYPXV /X݄+$rR\㉯gmy_P\5ǒW̏p^ SnO꣝BBLMTa* NrhlF$o m`npA"r*EWQ&=ZpUgJ,3`M1tb>k$V2v>Vq6[-'pnRfOj0Qe\=QxL>m7yv,F|wFz46-qU0_Zc 5W-}O7ڋСA{NU[p 4zWջ?MmlQkVDz!&dv{ښb1 dH l@(ިEvV%;MNIϱ/krH1=*T e~@&t(@&hزuP?j4\3PpDD2yl#&n8F|₻ :V+ ްo dV0F;3&b(&IڂA" F(DsUMnL!dM0Xzr@clxKֶ PL"-k- h'5RR2qxYY$k\8h*2:L-/.[袸f@`7@r %F:ǥMtYI_0iQЎsY+ךmAp $$ W;%w~^\2 rV>8nuw #2կ ԛzxUՂ Yi{V{U,Gs%zڷ֧9ն&{ę>kQ 1:; ~xXkl+9VXh3r'tw<^JQj^JEXozc'P;)3'VZ: 2g" =+>JVLW]MǶi̞j>kB#!ZvOj7\2%H|<3l^z4Ɓ*$W^|ں xzMګ"rwVWiVڡmn0DV=OcS #ka aNDH*&D]V*^;MJJXiŀ\4\ `O N?lk:°oq:ʽ쀳}NZ+kug{n2#5ZmTU/jLA+ x CH$Qx{:ys%ގӴG&mˁ3F4*@fɣ5W<>"NH|S\Q[5Nz.o8r x^,j[#Il2.T gc,GYV0 紞?tu@*4N+r8XU5LĖ9#U);Wi@]$rUР#.b'ޮ9)R5;i"Yz&KB̟Pk,flk1PPLx g]OޥRC$u[ gK:P6OGrMeT (gޱiLH XLPطmrޥR"G3SBǵcd!qPzE  <ӟ}rR(Pd6"kɩ]mH:gR  2;EJ;JѣjT5G_?['@qՊN %TjmA|P]k(?k=[ZIhwuJR$O^r1nV{>i 'yzCz`G=~WV&I_Gm+|{9ٮ;vV]wVjov=믣<Mr$q֫6}.PXum -T?YHEUyWHA3H|F.j|@NzTx b->rws#'⎲ 84vDUixrQeh$qҲS.(yTE{[s׊7Rty@6TlDǦVǃ_IvPA|Rן4״6-LtX#'N\ Zf$4Gf' knQ}h {F0` {6$uh"`5V9R=KITL9KG-Z#8Ve$56S>Ղv0(/)'1A%U D|9Fj߷ #3pkAe@ތF{Q(I@#Uڂge-($ѱF#cQ)~hqG=My -! f%&?|QWcel2[t‹$Ējds EbKOJրpAr΄ա`00*͗f`F:+V-j1[X bVHqZ`f3" 2OqA?ղisڪ`Z{:j醭xW?} t&oӉY$0vJ^6\3*G3coC?w־_R ՖHl+r汮[ƴ>YfA%Ni-=DLH:|e;3`@/5\?ʻ7/vЬ9?[9ZM͸- 'OW59|4ꂬn#[6v}L%zVȍ`*<r׵n82fTghhho6&Vm sD.HC[7ڈ uOvfj rgUQ]I>`1aKZ?TjYл_VsW]eoih$GHڛ2F3ҲUv)XGEjv0#jwemgZ8=k]ajqy0Tu` 嘅Sڠ0uBJ {DinA.:Qqf NMf gM"uR}7rVnOKxA]H&}c#qه'c;(>59WO&8`H^E_y!r2k㯛)orɵLrOvy?#P-DW=}+<i,EˌPWMԍ U+-<ڦ[C~uOX?sݮY$t-7Spp>+N? /ˡ;חx|U!CE5K'VV09gy|o)0z_{_\LJ2>,]ǩ}5@1LcI<{Ԣ&7X^%⊅juV^vRީC_7³!@p0*މ[i+CѶX8FڤsG+\NG:C  sY̶ sc3 EGfP TҰ\GCJ4`MorJ D@ABZhiԙ3:F(}Ӹ愨Bf+p0 Wy#sơRtz^4;l w YξGD[q]D/cY-z&ur# D`y8י>«qI+ٯ93I5̿OESbA%z{.41Tʭ qʳBZc8Vפ:ůyBIs*@ytzgNT|BF܁Ek\3ks7hYwwʫjIr]tb3:hX8]rI. ]cUtXd9JlA˭:@6,s A'DTb L`0Ijm=;dMb.{ E-*ȩڱ.(aX+X&;Q`'Fp BZv SJʸ%{\me Jʁ'=rI5$Ղ;s'ޝ6#"ioR_ܠ15,ݶ$G"J5KF{W6Ǝ OȩtB1ϖWc{Gڥ&s|tXҸ 1@R来8ȩl]W5.i-1ޥK#$g޲U11C>s"`f:JقA^cL u#k#U6*=봎65(85G\ǟI5r gnOȝFƱLsrJRs"tIL&3`Ư^e@`Qw'uNǼQ7}R9 #4 & m0QP.XFƕ Օ-хu<]#~BT93pQJ"#߽s-M,"t˾gU0'\tg~dLqW+]$V4&+ubŰ'>ȵi Mu6.Ij(}=1dI(-ZA3@[ \{V*xR@]9_5L礕=D}>gnf}i>ҭ] Nz460b`PH&`A`l̼uFb,Q3=(TϤM#m4kj\R84`eZXщYcڥ&#Fyj,'ހ7݌w(k3F_ghmVm'fbXnd)<ԷUߚ54U@PYf"Ȥe ʑֆ CåP-DD V7PITl [j5.I84"/'DDX@IT;`@hzP ɞmDQB'hL:Q: &9E+h ӚR[[hh&O9\@FOz5*T N"Ż=-dgk*Fg(EẰ6U:h`؊,[bıF-,<0dҴX z.2}YuΤ\>Y9ϵtYuJ+MtKC8X^v ` V׋쮒b D}.<ƼM5,@ b . ˟{ +G㯦fā*1;}&KgnZfizֲٹc=C|i7Zĭ ʓy=Og/ڴ7U*5Wm+*O+w~vrYE@-ɒ͌]_Zp.8vq V9} wE,Qq浩htX:T+tivue qI XQEk;h s5G@sZ\@nz+[ mdGozX_91+]ևN-I(T8ODtUg(EzR7z*x-s~#d`H cG;XZoPk>"4y bPmV"r{е?94aqYȾg&)nl$/XS'ګ L1w1nn=1ZL`2dV{}>CKzf'ԮjC+q;9s+ҵsy r3zu˥V~-dո ~4p=V%R2h\xnc,i\mzQ'{f^2MlMs9t_rA2AN7c{Nu9^o&[wwϽHs]$q{JA^zt=gӛ\zSpazev]\Njc].ػh=Z#~M=;Њ@v,[%@~WMzQ#\ޝ\G%2{ʋ^Z[``n GvV~-I?>ºDZ(:NHgV\gMb[/ p~:ѺZVaqdds"Zڗ{pPcLϭ(BgY@^[qꝽ&u jF翵{SqhҤ${nrlpX@5~pLcc~.vsj^DUf/ԦU*:#KKtɶs9#*3>=|޸vWǑvq^gq}&G^5|"ZQq󘪕>Q[^L}}oHua`@]YBݭoꑷ~kG7_:n 4MZ'k,ea~>~cZ@ˑp$i7;UF%cZV zz"8 Y[{XjEDځRD>(Ww4}qRYzsޘ[e!;ҺM6n/xQ>%k Ek4mߨ㝬{siF5-R>QKdO5N5GhQ rƎ#Cm$gکqcO|ht=I,5>. $tE5zx{ZYG қ.bG7U~jg9ɛf6t(f` by/4 ctE'3Mn$ޘdIlH0۾Xza9M1>ȹ OLgm0qT{⫝̸P0ђsq'MkցVbyNMz~m}&++#;>ڄX?+ =+ E'ތkK"+u5@Pf+q/BX޺9rhn ^VQ=QT zW7HZ=Pg/dkew=5G+X{y,NfG*P66Oj#P|kW?]pMtjW޺ ah!VF3 v<А=RՖ? <1@ky2:VV`I5Bo[xݸnoso(3N;}ZZ jFcDԶ[zT.,ظcR2?ԩ**kS XذV1R榆q #,: I`(E#YM,``divlv(&KEE JDXs0MMiE'şPL7z<,3,K,8"H*č+i[e sPajd_Uab>&G;U5^*Rԡ gF+1Z1{|]Wv,IXq^ckmqpJ#oWa#p"k5{\sЭ\;̙9:ѩ%NOȫ5-lV5{LJ%Qcl34AA@38P0θDI~=<"-RHh"bK' /8OJ])%Q{`'\vWӞi`PPGy:_1Эi@*-n8}plIyZ+v2I*M:I5DEēXkQKF"ꆙ: AeWpX]=]Ć!31W|~>>u<{^c1L'ָK$r+#5Zޮ"CZ-H_n~>D.`4&Emf $VlY ENbA KC jO#DkYƥn jB|V5 $I m4TAhLh03@@wDTl88=(0cAIE;mJ4/j /PpfNz{U }r V\MK>VX:@?"wj]u`W'^nƶmJé\o];u^rUW2d:GOwCgr_4<ќo1|C$V kr'U9exS)~M/mU'tjQxۄaKҾsW9s3o^ ln9s gSkjcjӢ{Dhջ HC]$r#ۼ _zN5^h#21jjo* ~|QZa:\SFh#ְ9u[A21MqSY[ =k'SzlYcG+^u>ղ^I$#kAGڻiwB4,1E1Q>-w}#k'l[x[72Χ9_DžxbI'x/'2ē&_%WYzOK~?> o'>3[9OWM}#p}.<ߊ/~#ز1k=kXKw"tQq9˺PeA9ԇ{Wh6GQHv, ]yF׵1Pц.>ծ/ө@EF?VxJۄ2(n=y@am5 $N F*"A'Z+&LLu]ͻh1Iko`ƌ?C'J"av홡t$Ӿh8\ɞ~k<×KU&3k9,aZߧAi h8O]eS319/WNre%I&9kR _,rDDj#TXmQ'ԜW$P 7=*'MZ[\gf P8@hW$=fET84nmDNjG@rk+RvrHEX>š$YMbdjukhȟaRq":3+-T3=,iՃ(2Cb:#1jTƂoqA 5z!=i>0`v;wA b)AEϽ`(AY[F AnYk[Y+gtpKB R͹WQ-ekn7PaGYۚ1zŢnL~4+eXzZ-mgRqb,3_`\,A9潞 y\kc;c| Ĩ z<ڵ40`uU4"*>qDN6drhbÈnlR,#VvLOZj0qG‘MD`x r)phUDz$b( 4ݹF{jP9=M2q3H"C9dqR GZo uA%Hb,[Z .H 5u3ޓ;ѡ`yL ҁL`A;DA8GFmv:SҷX0&s֡\V(q g4" fErqkK1<~f4<)= [ OLUdbĖQֵnnhs҂͇Ql8Am =ZBYȀAҀU~kR,MZ?r^$Tb#Ĭ,tv.VSZN?lX(o2I^ҢIvmq+ؙϿMSlCYgju.) 5e!đOV{.iD۶T?jO8jG]^}z[o3zΫ.+'jkvl.ykISoOBLqZ#inC` (O=DDWڸP6'*gƵE&=|rrn) 8w?QML+x:yƹ u@0kJFU}k*#Zx9%nD@H݈3l`*X'.90FHtUUwb(9sN̒IҴYvuYUcS)%x1XSO^Q-0^o-x'zWK@ĝÓ;GGiёhB_--6of<ޡ,&Pw7d;WX^ww<)s]qb Ff'1]1 ZCzz.TqPhֹƂ@Y'Y`zTE?΂,vZ˕rPxX'tcf89 ]qxdk5GX]?HW#[vHfr*٩ɚ$2dd XbpnA@׎8h*InXYD74@g:5k{$cJ~OJ**·P(5+Yl\21R&P9Wi1F>ɬ+p s@{ =T549_""mEQ!b3Hɷ9 9>b[A["ձ qҲe 09;,8Ё=b cފNT֦gNdzV7 bHlk޷ )b5'ߥt7Hjjv@'zs*_tׯ\7\wç3,$d{suutę5Db>I=?jԯrsQfפ`+u԰U) 6́ީjci3T&*ș*]e& UP~*tW$J ms@DI`;ҋ?,A" Gz[Vu gԛp1\:z8}Z:gx{FǑe@-؜ V,fk\Z[e8ʺJXMqIkW!.gN@#3dӽ hX8cPō2zS6RAj`vv8o,)RHe~W|#tm1__b!gt$:Y$< PdȠ&+`s;V۶5k[=ehmA0=`L@8 gD{VۤV$`LԴ[CK̃:@F;XE7{U 3@D195@Iz1 }l}p:4H< KLPFY;;4bEv%Dh2I4A2Ҡ?ډ?Gz@)V& =4IV+W=[=a\]4j  av5_UcjXpqIf, ='^I:@KBIFkOB`I>UA5QdZѬEl@]E6fcvJ͙g9:/+c{{${_ [%Ρّ{=1ǪfڠAOZw|cF 9%Nx+O9Ez{yMzQ0K]#r4U'+9OOV ]]cf(6w<YAfz֤?5@^jl3 =+Zл\PD4bՍ$ڦ@+[+p ͩÏ gI&}xkn;ڪx/u?T5?1Pct% !\D*>=:uF'ڞGX;PY Ln#GkӉl[pލ(QrYDVkSxLV4fT HZ({p"kIq]1 čF=@~**dg840@LV6kMrA-'D0x;% =YjMDžUִt6$7fwFC(Q% v'ɜAnE+*}4E̎2m(ixwij_[Fr#A[[Q jtb!·9y]MXbG|ә|6g}* ~kvOB cy%[[X"ٴHUkUێ5ߞ\O7m^˄$Wy1ë-&KEnM:_ ӝʄ~\뤍AnF"hV-J!"jrq/ z #Uz-$sڻǞV}Bsn-ē6-]sc?5KdR%X# Jb" `f@mг2= V}0ǩY(UִW meI7F MҲH1BqXpK 6~5m=05a( M"@5 W b"T{n[ްW'I$b ?O"ہKZVe1nͦNG@gS[V5n*04XSf+2;T#6{T)e$>@A,m=='PB𹆜GA0#˫c%Am7bpL5GSH ^' BӓUgVnM^m$v]$r#5U3GAO?UwH\Mzcg].lO$XۡA'޷S| JVqvφb: fcB֜ȟef;UpKpmDE^! f1u7n+X^,LO1 W}͑&3upހp OOlRܤGQT@;d1P?sຖ]Go^~z~+pG%k5;k#q٧}(VyYjVC 4`8 ,"Sv8 3?#ڨ&XLL #ޱUN}Xa D=Y!*X RuC eZ 8[;tZ'}`'%C+EOh"*2sFLt HhE ">+46L[#VB,9ҿvp=Ő'^IPjf d5!Uւbgށ3?4lT0A5ā618;hwozv"`P0FdPZg$p+zY]}H |U?Pm$Nhnju"h" +Ak{u ڂVk҉\L& V s$qҁAbO#ִMc-MAhcwEk@s=*ѷi@P㎢Zӏ:Yku]l։i>??j~5{MH0- lN+k5 gX`M 74Zm֣(zb 3NEvEYSk`=̊iU/ Ȩx>a$Z ǸakYWÝhX5:^isM.ݵkn'q 3dmꮠy詮v׊ W-^"רApqr]8\{ɵ;θ޹(唎+~6c϶߂进 T+wl~oyG} VZVN AO;oW{EIGjcO_,@W6OTx 6rfIx$ 'IK}O8}]cRr ;6>k̯YcK g=;_u.9?k`}+!?zmYmǡTZ <?ܷv`&G @֯ 2zSC~U#bbn4ҷ4{3HLi͖֭yӉ5^ TpiHHYs7t* 23fO|n|<ު,0NWO*m eӭu8{?% m@N~UT3Db>R0V_L{ȩCtT$L_\OHSs SW ktBeA`~~&{> ȭl+2 t+O޳Xr6rgRfY߃ZýRTl-zVi1/1zim1bޑd)StX;x: `HONݹc'5k~ APFNN:kw!+>kE !bf]7aw(xZU9V'2+QrZI]b*Njt\L[AWÿh!&-8фl$EHVP;=ERIh@FUr 41"Y!$h#R$N]"*5>*$ [P~;ɭEK$ ~Wt٤@lRlXˆ&{PՁhcqW*k+]ť3'+bc@~k;;ɓ҄opI=9}v+gҟʛ <*}7`A ċ`[^s kDt8_ZaМWIS_BMC"\UsĒL:eӞ-$U2{M3xFZWi[g4 4Sp>Սs1<[Yn͋mvJӿ/vIN0-ח kd.qQ[ElW5 kY- \+XyC "X2zW"MK h典&HAO^hʿe'Nj徤RZ\F^ }>7Rs {cU kX[ ޭ₲IbsҁPN Z/3׽>yکk`~ $@*NG #$(L.&+0 &S#aX'w vN%l#.VMc` cQd3Zf (Al~aRȬ8x=+d,Ml`)"[xv$K+@2Iph"ʤ@"6&}% 1AN+ef2dz5 Cz)qRj㸎(h/-C"q@Kb 4 <c+>QDyDp?UDBOI5/_2~=7}mw*ީ5__|/5w7KZд0TCnrp5&ffkuuZ}qǵs} 9K3tu3+|0iC tZs6<0ܹ kƗ醼x#85[Z/_ V▫([C6ڹ`|`=~:H3 'eﰤQujҍB j-S z:)12}*?ա!Imd޾@G Y~qGfr#Dח d߫O/'Q4^B d tǿm@|r#wAd+I[㈮l@<՛zKh j(ˢ]0MWC@ f#5s͍1ܰ tzKJtʷ#mw<6]jʨ>nUoEjҝq=z E%7<5|[(k:A2~{T1ux V:+=s#]n"[ͫ$׭NQ7x$:5dž0>:7ڧY3Xa#zh򼈩-۰aVXY&uT)yjqi|,f8#fsOG\JSƈ|QG^x]fз _?qYb實Ѯ`38<K($wKh Y5K_6Aޠ2ixbnh$nR m*X ڥ3?h8B/>PŎ<8OrWvڽNa=tϖjQ7gv+p ha@({P20Ah0"A9A ۰jOq2{O$Q嘒"8rf J [H,1I LXgHh7S9‚ b{Y=;Tzc85iEft"4 "}54VaRqUl@c ($odV6چ{Vz'}`L ≰zx֭ٹW=k. R3urwoj)D3[AQ 5Gyi"RYmZeڂ;E r6E LN?@9Fk\!x4Rqݣ @0*q]헒q+XȺXUjh b1Rƞo#`GJ 64w71Pn*~vݴ4qSq6tAv7Osh#"q3 2)jZ¤SMf2 '*Ĉ U1h9ثCjǏZez| '[U<`էkm!Y̤fz5n|HKM{o Y~kbgI#aJ^ſsLFOyϏhUkӴs 4q: z]"[SBaˈ^.ؔqt~Z||~̞0J,:޺O OU^gIgk5rݲvݓA]g>՝^3u#y&)X~!n-$*ڟ`ݾZBKw2X M}nśHU=2 geZd"Iav^8R~&W[\\凩¸>a_#y_,˚}yߢP-BݼydIknƋ.-ZMܑqńY\SLY>"o#tK1e)$ 1\af7(b^yWTqWfcB-sfsFHiX(,{:uh;p$F\\fTq7%ftZh"yUSbM~Zs+}q{foIOjhdx3^j/6F=jۦfjpIB~$l(>[h% a-'dUӸ\k-ۄ$rxk5Xc]d'j1oO1V8cGKLLjX}Y *@bſEfvMeGO,'hhѡ]&~ c?5v$[dclpWtIiGFAMiU@U)&ڹ ty1z9pbك#M;+p Vzm`hHY\Bчz S'4Q9#m.$2&h/}+7]n  v^'EbYEOLkFmCF8~W-LP:*)R ج]k%LȨtիiA8*/ҵeZ j mFL.\%H^}HnuK$( q8*%#"++E\gnдwFR V]ϒ3elY-*:nڤDI v$Q:sV=I8UNm,Us^RH+ I]OH 3NZ67(m?cq 8GFZ0]:\Xr[#NƝ.ڦŽ*]] cA"?ZMMM] &@Z1\ TF"JY: ڬC]sGP?zcLrp8 3]esxǢwP H":]b+PdVVګOZv Uhci1ԜWr(3ǚ ۳ilYEAjS?zVtv6 yz|Ot q!:=^`Mh&f"^y} yuvߦ@.[(H]"ڰq%a rk.} ڢU.m!``.ykD۳!Fǩ--#l`"6iMyWKI9$^ x}<[}B<\?s@a9I Q[A3Z, `ڈEkuhf3މqި8v =&s"@ "X`L>  ?ⲈP>q%inadqZ$щm%t҉Ӑ`{PI2$U` iڥܷ% .(3̃3Rhb؃wt2 `zQ(1zvy"DU39kOmku2kM1R%HF="}1(L a'"a69Dh`qҁZ'С 1A5bLPZH?Te=QZĒ@`bl{aɎLP`(ȏz4J!ql39h>Sn(&ô#@P^$b@VsTͽI?ւ;XzVP**1gӣ~²Ľa'fXN5r] ,OނčĶm`cD "Ooŝqv橘R]Xns\uh>Te8znsFS8X_H"ozĜ`W4FݠjDU_ʆAV=vT[s%|~tW;\v0c$]~ܭwYd=zߧMjK$&p6ϋcחUBdk>6Ǘ&"joi8ߏߗb \~#zkn YjG=e>DO8[9N^P+l @a6ذ"*qhAް\h`xyF]a)twPT `RHي5v† u{#nat5F3'K1KZn'VN۲ns+u?=3Wx 1={R.)E> r_(.i,?:/qrېxSEӍiK18F O*E/̡tVh|!ʀyEܽfrχٶdeBE1KL?H1P=^er*w?:AAWU5aT;'6[IOQ@7)`WgS'PMY}QU`fS|( 'x#|?wN'Z(B=,?GYJF|{]Fұٳl蔯Y])xAs=ym``K|j='= HO,8BJc{Pgܴ>5PCc2kTͿ'LfHkԨkHYVKz`ǵvàv,ݎ1]r {h\`X 9V H#g:,<Ef'ک(I8?  zVhJ1zDqH1?]%h"[8GiJ؉etvE`LTկL^j@DY;LI?ڥK>*tw(wW;lަ,~#3PѤ=VF VrA+Z"9֠Ha%aX1Ҫ#f>LRՏ֬[w:\>xRJD*0 l3@ ޷sVWF^15x]K U x5BY͋{d՛Y hXBIG5kCvvێTطmRhFA]A=*5Zk{'jucDFָ驫,z54l<ۃ,qET ]87&dQB=䙃X³c'KHHz,iǘOfup_4t5@zgr h mˤl*8?kBhA Sk6]7ީ5;.~b+h- z-bH } <z5Xe @#̵ fy RN~q[\>Fi3"+nJfr[Nbf hZ zԩIyN`I4i[Uݎ)Y)`C"$M_*\5 ,ҩ..2U_"XxpPL޶WW%?R(j| BB' DR2m\km";<1Qs rA姂zV7Z 8Qڱe$};ʺR WHz7m1j\b\#n9K;L~m&򠰒zG{FXk5ЈhSXf{H0LEVe- b3p$[nUKJH-bG^Qjqž+qoG:pnXl~nBIVמȦ>zО-^c_W~Ξ`pOz7'OE{=DOQھwy<#BQ/ھ?>yϷ]v|JMW wutzqSuZ-SE=U ,V\ЫdBׇ)V@i@&z%_SGI\]= U"+f=jr'Q\ާ-Brnx<'XZW `kx>,u<#GUT 'j<|y?6~E^evcc[P6َV/ L5m?[O*B ujf4,x;d)cN).Xī(3ښr=mZ& q4[0'BܶP,>m*'8q]|QУp1 ƠYmſC{0/*LhrÁ[4Uɹ3U[͓Nkӷo!T֊+ #"֐yFk9 D lC n}@v?z\{KvuxXj,v6s$G:!uM@LjӕR&Otαu%9]sc/]U^;7]zw5W:g[+.rOZ*,sW8䑞uXtH"=(`SATw,L0 ٓG Z[;WgeR;8Uz;H {J]ǥ'$)*+7aWIZ$(=d+\jmC$LĘv*ֶ d 6:EwV(ǯc\"M:ݷBDmXm{j ^Dž1n7"t5ZnK,W#Ur<_뗹n*dIہ־>gkn&fIkU$_0]cs'TA YQT b A%@Y SzQ:~`OcP6`BԿQ׭ P&EYLG޶V(fWDԕG3'މDI+06&SXׁ0?twfrg"}#FO?Pö@3~ƯQ~>>+55ˬ@* X~̹oqmӓv۫ L[`T]1PײpN uSjh'[ _9KwsQ{7\AEdjsfEZ3Y!1 ߊVwUY$~1oo[=PmZ[w n81KQk C:cW//{>zzxrXX_;?SMwAY5uzԎEg'w[XZnǟpElF,ng\Me$*uxVN+\q^1֝ɹ&f9=v\kL|}uj/,8W_ *-` ?s} !G~j6u\ #޽<׳ĵ7T9 ]ؐ3uԻ3DvϡR@ 3VJvLj-lV74(=Z.1g$#OJncs\jk7Aeɨk*15|%KGBq.iWj#YWۊf~{Eq?TN߁8jx7HC?`+N3Yv2>i\qKD-x;x2=Ì0(<2Cf8cځ=2Fx"dhUQ !Is$y87.̃+3R*j1pppk-IXbIn_ei-RF{QH'hFz}g{uĬ_K7c!܅>ȶUoj[ժ A N.)b@ qf6ulz"-\D6MMG Xs^??y|^="M9ֿ9<^)m8zpTA'kke.I`[Y"u R5QyN Fk|QToW [ЂP${UԳd*@Fj3T<-'< k`[{৭;(Fwr#2=aXu?\DRgR*[2{Uc ڵ$HG@m _H`VUil#+n7tvUB$κF`5Fݛ,FB] ZkWR }s\K I梷汍-8)5m3i_tW"G7 f$+-6v{trpkF%+Ү ;AW;ڽ:Uʋ,+p {g+y+(0^]x Oj *AY 5JGZ 2E57OSZ nS:F`Leb22`dֆVށ\Pd|Vh _jhDukd` iD$ٷ4Qfۀ`H\bXw`F[mD5!XIA{aL߼hNg918#as~i,.h XK*[kp0FU*Lf&;>SsjDbrf*H y_,ZS(A-gL@W&"ظl(Dխ21Af(ͫ3[!.֩5b`{tku5g7ݞI^O'S[7ha=`a\vf%Fњ)w.->QsP,LO⥬1 %"_&:3V1kOOA`rk4ő7j5RTf܅̏Qkc4ɁEsj-ޗL`5bȌ@4ckKm.V8aڈrdP9Q;:~0A Ed=OL銝v^;Vz{P( z(WI*AMVl9p@1sYm\ /,kkVH87^߾Ez?|N="S+y?_OЈ$.'|2mǵ@K^MlRtvAT`[Z;ʴs]#>s?yx(&}xڏ}9{^4)e$a__ywHm2A$dv9ik#HFf1p+s_U}, =Il?t^}];j|KSm]ìw[|ϠTZ7-sڸЮ̏23"k*=EE&ұsZ 7w9'E'#đڢh}}<`| TZՇ hMBt]2A6Ǥ–{elj^+:.:tZt<)c(y(>b#PGicB@>([* _Im7xi,M2:\eL@p1A'@(qj`|4aB ց'4IA5H`{V0i,ArwD337$c#+yZ-'-5Ωi'&>Ɗ K5jZ:Zeg&:T7 ~8nXشT5lqS 6P Ϲ5kzv-;{ m$ 55g(-Q=*Dom.hvTǸu;PpH {Uȕ+&Ij?ՐMR[HXe'he|#ފ (: kuur6]$tz+` ׭r2Mqj εzͭ8R 8楫{VTՐm*e"h n`DVbWkBͫUĈ|&U5 2O5i]*։VڷQ`hr]NU]W;G_|ڻJxZyn,"js\y׎hWN2s+U ^~+r'm`~!۹$G5G{9u*[5UĮgrn-d ?P"@\|ˁ$\vųmJĨƺoYTDrzʼn=MrR凿ڢ(8zK`vsR`z -‚dfh4oI{9o5hu'Dž}Oⷥ2$w51<X;c޽ L_ WhD>+@LďT S1@%|(`AbٲL= Q ׾('!`sւE3UOtӑڂ![z mlԆY5F8 91\MbG4UMQ4$R%bgD֩p{QMZ9Poh@r(s$}qH@'[p E ځ~h 0Oz Ɯ:MP 'Qd]zwa+0&֤3[ 7@h;18=(qf"$wa7@z{$YktaC(XAцբEwjĤ8 .di@[r*D6Ċ2yT ެIUJ2'1")'h.i[uݜ}mV4 aNF m*'5BM| 3@ &Mkp@NH1+l15AQN'Kt0m̎AeplMBZOH_~v'lXJ%ܿlMab>4g^2bg2*mP(#tܼ!`7z1ʮ,tȚ֨&k#ް5wmA1@ DE4?Y[ާTXDh"Jw\PP+O1i{EHP}1;kt q<|UvV~㪣s&NcE|i] 1,uʳӏj1_^4oOziG^5L޳WmAVӺzTizhXzS_PaޤAn$ \ g7afdTLjZfnцeDZϠGr뜎BV#"My'޼Z)ݒI5~x¬lkmHU|-k%;qq`"mQzz lXngzX=OX?Ȩl@j}OR'Ms j[IOJuޮ`QzD@ׇ?> hLI9z~?.-_#~[~NzF+*um%h NU5I8X#&9՝McU\O^+jՋ$d9~ǼL[`"_~V^!oҶk +^=oWIR[0:j?~?=rއF-GH&}׫#kynƞ-PgZqro[D_P 1^_9U@I {^eVdۊ{n8jz6C]P} xsd'쨚6NE/X'N?:.uH5*t_ŋ$Ng?@,*B~EJuxxr$TE} Vj,k{\?LrfJW2W*zriӐC ?֯LRŋDD@Sݳ":miV+bDL#5LiESW,!}ӃR GJ`yfX|Q8`V պ+$YQ}lEu69/s"kNv<= 3@Oڽavz%s__!;һG*ǺXue$3BkHfg \ kq tECck+$:|P.\@w5Qz) |4+3=\j7#S5Fp\q]c?]d\bfE[KmnA;F+^2ǩGEP΁0jhZ\P=yS/j"Z97mgٺ{p+#/ope":v|SuLqA+c)Ǯq5(3@1^Qhp`=,Y38j3ra#:}E"F( Z"kc Zz>sA z}Fpp("F"8Z@$|U2" L{cGBw5 ՞ZB"{h.OV)3{JA9Jt4t֐IxSHY2(He5#ްF 7JOJ$%=pzUǽh*2" DE H4bTGk2Q"MM]Lm4R+h,PY'&HB%M{9סE@DĀg80@e+ha7+ 8 ct7U0^ktT LJ fGADHn lM_h;DZҝ@aGַ6m1 Y۸#⵶^y}0A (&mgZ,Ym?:Jf\ B㙪2=85iK, Ù$ަq*#R¶-jn\g &M-.$0}#8zNwX1>`hMtaHhFETR OZA `V-4yXKvkk$n(XzaښlnXگPul)%aޞJ|V utlzDrk}U덹Y>),v0VqyA12N"[Yi+/)rEsvIGCYGjӹ/~j&̆#+1 xߥczխ97]GWJ<]Yj쑸)F7ٟѳªHW;<#|f֕78v0Iwx~DM}YrLT HfDo_+-}G`ZmQTF+}eXn+b+!xz*חcֽuQyH7,댩$Dt3޻O"^4Y-V pM_#}[޸}0:J{ipA6]Iz|TW fTTڨr+5Qט8^1՚o^B.F{օIϰj!u,6TC\Q]gj%K GQ j {P2J`0( n,m Q+@WN$v/I,h'z2aLv<# \#ݴGꠗnJ*NH<&r D5"T~h+3 ${ѕ+ `v=* n!>ƴ/抖Q99 ' NLB{$V+綡#'$0b]ƍBͣӌ u>nUkP{ڵ.{En^M2h*\zY$:۫5;68Nxk=;nauǟN4@OZJQťXhkx~kq["kً`O5Ϋ돖jۀ9-n{rd̈́8TV LʪIej'hEH=`|JQUVFeI=+r3Ǭ Hs^cϼU..98rqDW:̍bsP,°T`"AkNGj0}z3lUTpj$F'ndV1/3)SSmT-KL]M/=G55}ĂXHO5ǟxփBwO++Gy#- Z ]Y1Շ,vϽ d*".j$GZ]#;y2:s\jZ kuWfRgqJEQƮVͣ"qON9Q9+US<Rs@;Jz 9f@SV*(Ua?zƙfx7\?˰'L< b2>\c_s=<}'Ga]#A vWX*H;֥ԃ$ϽP,u0 ldډnV6212](:-h*A&#hS@[LQ jrCڅ0̊Ѧ 5#Ys L+[J tn.f'DqI3?%PH'ް=Î(ѱd~"$ej 9ͱ#FԶD.( juAӳ1hǿ4qɊ I;("%I A&Amw$c@&hdVlFF'ލKh("[p7QQdA@Gh#LaIPh&P 1=HqV '޲3\֞UϽ 3hʱ\޺D,Ǥ'D4lrw*$H;VbEn`AQ )H"sAb̒WfD7rXn@fU7€c^r“$v5`ڱ &ajYQkLX ѐ(ffR9FsS[Xg(*2iR7d@mZ1H!՚WN BF*@[l5B-uBFJ#l] '+sF e?+vK<87`2Zi&ݠ3SSZ:n1?En1x]tlrI?Z,ǽzuU!1S6+#iTS@ frN`0@X 90s~и,sEhEjFh:@%x:8qS @mU_IXu$:u-??߷= #$?j~LX+#]MEMƄHfaimEuܺ]%@H,r+2ܟv,½|x:#^gk$\|/vFmSq`$ ⾗u᫢{d( D{Wؼ=.QRn<[x[e'>L{=uzbҤs"s]'J|:aui'bk+Wھlmn^%*@wYs 0][4% ' +( kMS簩cNƝ[Pfoì0? WLu-=;{|j8O=[s#=@uڳ@I`a@"k׀;H5V. p" K}I&("rz=&f@2SFh# ч>f?~Q]#ˎ zFT@WuQҁXQg5+rcEhw@h wBIhr?B߰N'6 *]0y wVd癠nG^yj[^/r"*y'JWaĊ]#>5(p=s_?_K'HUH߷GAbmN֬&\u$nZte5"NPcS˄CU7.zP]K@2r:hϩۭ) Kw;GHjE~"q){a u6椽?z[웈09?ל7 W9Zúǟu-ĈL++Z[q?ֵ\Ԭ;֩5+ʨ5lPb@皤ڃ lF#8!l]J$G_V#]3qP,&Xh5#"k`(P٠t"`N(KwZ5ngz7FWI_QYZ2R'ARpSUsP\V51}hϩ!nH<Ո0.( Ǥmw2-ЖTV%(ֆ}v'h$@Fah$pG4AA0 I Ccڂ"J{ԇG*捄w#0tG޶&k*@M!&O3AA$!zs֍^~CwIEf`nkD4ϺAGSFbL 9<0[Ed@@=P3- (%ppb}.؈4PTq9.e:̙>լob {A N K!h@LU "pjΜ*=#5LCSA, 0qv4PO&_=d%3{IY{+]~j/- ٹ0<Vy֘!U܂?8O0IvuP HݡCڬ"TsމJelkaGQu݀Ai $o{to2,,FktWv2%`UAiL|Ԯp7uUFOSH- `~ &F R!b ӵzy^`5&`RQڭ&U= )v7Bn[(gPEtUu+,H#d9*n ϱT4f縠IX~h&Kh+3^keUhwM /5RTC2BzAdh}DFi=Ѹ 7zՍ!33Rƿg ϵʑj[[enzۊ1>t#.~XOQm9XCF~"= ="H8\Vb[x{BgUu95Z6$v=(Ͻ6*b t, #Xjo9pּ;̽&qCk5rsAMeݮͥ@N|jI`?gN<^Kgkmv7nR?lWO^/<4= )Cl8=:pkJ>g[zub茙5ǟ. yNysZPӚ<*Ȝ5<^ '?&ZZ.᰼sg:\@ٮ^H1u6b?Y}Uc_ $_r_˞*q5`p @fOf5gP]?\[Qn6tHV;c52OEVLcwŽ^)$|MaY l0c4[ٞjtÖTVh鴞\xk>p0pC/'FmFYZQl[-b q9'h`cKXSKd$UAbvGz A<^Ν֊.vX,dcAt] <^ma {5G < ϙA~im8ޭyh?j#oVMP+#t4zhCčǡ0J=EN 2)?ځ6[ яeKr1X PAv#jbCkPb@7m^{ I :Pp55 pZ;='W'b'ǫۙOEMwWǠx{lD<1/}>^O\⿶χi1NLoD={W'o*&.' ܼZF 6Mc"-sa ?1EYVI O2Tb=郔Mrj/g'>ղ'\/\,鈵V^G(H1XkD]i9^-y~fT#zg$ts/;{{WHjL A5h ed߂pHb}=6:EK jOmn9̰*ADVځR$mER6+(H[0LP  VaCI#5J+,?hH2(Y#PPPcVVu;XJ @21=*V{IB%piAwHi VUD0;W:S5E_cy\k0ԑ}GޘԌm)ja4g*MTpSC(r{SA4B$BĬ}띭ڢFΒҐ$`VFQ9UQMH1ATUH[Ңe-\d:ӭ:sj%jܢT;V=#1%vQ ꎵ#e/4 =nm1 |PʬUpF޴{w E58eۚSDk"A"oz2'G =rxˌapky:}+5Bf6ĉEwʰ5j<ʲzX]"jR@T.h moqSUe:bUGx#$tU;? xs^z/NbFڸGi:Dk|`: rmq5ʩNv u[''@[ Ա]Y[+[Dv#Q] 8n,n Ǒk^JU~M͉o`X's{:OJՋ@< _oM]?l]Yrѳoht4d08W|ow_Kx-׽y;ߙ>k'fj$7:zg\Kل"8ث4<2&Tn&Onߟ1ï%CE6n H`O@MMd#ɽrc'40{Cq31q0Ct%NfT"Iz 5|4508tʏ k6pz5nv1۟ƠBU~PFjR7R7K@Yiv& ^S3U }ECp}Yj2z 7Yz7o@3;}s'( '@{ѕ^3Ef0o!<LlJMNew$O]'v9(.=S=q@5#0 Uz[G5Up0ζ'̱]evO07UNzzy>Ͱ`_u^:8_R6T⫡ݴ[Q[jM "(ZH$Zls7r9W[hbc=@u'#Z e.YiGjn, V'\VrzW"mb\aJ\ } gY8<~WYξdd#ajT Ĉ#zn1~NuSSwˍSy^APQf} dhkx 'dYCzV+JTkLUcjv껿uwPVI4kzvA4Q ѰAkRՅJAEOW=-A1ޱcdb J Goz ׬TeXPE(dRm'&*kRؤfA I4Fj#E `{Y19<`0ft L Ym#x,hm_ u:ӎ:WK#b֮ӕgT5liiSy+nX@Klj<测 j-+悹C'S[ZQa '3Qfc~5 y CdLܜG(LA4WZNT#$Ղ&J1E&1ւ u3ڂY=($:j.3= :۽@v fIWi2@ތ: 0$0}RTP9\X2EÞ4lnh2މ8B" &Tuu49lH&+L9vщL0`'> iS&g' p 0 !6.4($=Cw(Pv1[:T #02rkda\8ě?X b8<|3W-`q+$e6'dA, shtzJ,Gu7;SMO#v"ֺY])eK-!g^3FO0kqpɴ(CSc5M431mKh#kM NJ5pC@$lP m?y6Ȉ2zz]B48h h;3 sq@Z(ބFOc/T $cQ5 d H3EV2(WU1j-1ez}S/u+N)K΢ƚf v@t|NļR6éL>;W*:}FM&UdoK\~KwxVBz["Ɵ.n{Fvu>Q60?hҪ ?h.65oLQzj1Z_T+Gˡ7(:m󐺴vZ/- p9j,/8WT ,dnw雐"vJ6YaֱUKn5-Ε5:EfG榫M)S,􊊨[1zkZVHxuEEZےq\=,qXV9Еh`}Aqrs47`D@I$4r 9ڦGGp =m5ͻxl8%6QOLHR+kETu]s>0. WwymqDPݹ缨 N>+˅r@dg޺*Ƚ/p1ڻDQmiUhtJA(:zу!sUqxArʔEzW;%H g⹩he;2֘DW;&Vͨn'n*k kiĨP&z֚⺱n.HHי}Ky@ugۇ~3kyy8lR]}\϶9HDfx5 @n4U Z4}HtĻzGV`K`!0EIRk@N3ҧ$H^\&FkNEٝOڂE[#Қ$HCZTfSނ!B95·CdJL [@3sXcbRJU#y<~kc*5YCֵʉ2gѵ]C  zFѷpAr˶ܻ@x\XJʮnc~A# cqIm'zE1\Hq.[:\% ѡdsBt$1Az3C :Q R,p剙>-H Qk $މA- Jݹ!g`9DF2ސNǼ@tԖ?h;y"L1ҌÄ.&sDhlaVNAh-QӚ&ݶ=[m|hlhVhǧ[})[ty٤2Y-]džڛ$ KϸP ymo¿ -w4i#ӷ+#S,}uǮcFVm"^?7y-J7m=V}#bǏQz} PO\WMyY<Z&1|)r!6ZiTK6P`5À@+G3P2{AwoDZ|a5p:&UH(1GRu 8SUx[cA @5Tx͵qKIyYVc]/-k5{lXӴTcҼ+R-o HָZ?: ZO}q E1C)2]#¾UvsMk;\nYb:{Fŭ诸9]%kKfHuH$ =і#`'#5q'4:s`\+5D M?bnpGN5X(qކ.hud"G:H1M[} w^=~ýԠ=pFsM;%SRB8$E`u{Pj2+*sBP:o*x;W:?C#+c'{k~='KKdq^ZtZpH-GNEۜPGP9K-)jX@EjkpʡH1C!5X"DWu[ ]cp#9( kM Bbcڮ9ϸ$NkU77P+bU.*ci9ֱkjs@IN Pfe7.Ӛ7K2ӄ}xYZ1SY>XؒPM`0XQR=f  4j[ph fXf M(ϽV YƀT9@*b cg=w9' 1 NhLϵ<"ްG`ǎf-=*ݺOނ2{bvDFaiojJjI&*` ȭ} 9m[m3ڷ(.cr=lԃ&H}cՄ 5r%LWYҡ>2Oj#-kXӪtͧfy] s]q4f_-TI- *3EuMΜ^jt:($ s3P[AVǵeF_Il+Y[Jvƫ_xcvq?VZ7Jd 9Xg7N~UC.`%h+=jefOJ경 'SҁpCVli,~j?vkd9<|T EoP*kc"pvXVu,`PqH .TEFRY L[>ÚV2FX[w$[BXh#IjhW68#nnqEڻv4gTfEnA xvڔth#mFq@D \>H֍ d|WkSkVΜ۶H$VxM2|,W+(G7Ӗ@A5/pȑ5Tߩ_6V0{ k5n 했⩮Eሖ bmYѦd֋$ q#oܰ§XFKGNbx$֑ݶӱ+@ͧqy$Oj-xwL[//L9s?V}V{7lZ0VyHyPn]$mdeP{<1RDn^ڱV1Rm"*19aw1p:tp_6 aQAo M{Ŕ  T#"bLQH`1^$#!]`j6^ݫE;pn#n @ה$a47[gE@LJj1z.*Bv޹ncپΙ.e-S3'W_S'ln+tsf \Y @۷jSXղg'sĔ8j7̉L,4jya'Yr";A]-q9vQI WHk.b2c]rM']drVɶ#3Wkkks韽tC\\tck@j;vɚi_WYwi0$ԕX Vh&ց AwVn*AT@"'ڲ̦zvQn@Ƿ8> AgacڤZ02 3T2YEkxjs`- <!{wu 1,ؘXecڠY[}DT utSll2I䏊)YeYX$Z"ŹvS9ZoRseLt54hYe/lZTLSZӐPlvhhGL\T,*HR-_R֘MVKXӮxKtD1Y%d7GMZ z{4|[c}8'q!Vڷexh.'pfjeH0Rq>h7YU3@O0HB*ґ>r:բkwsW++7'?o'Sվ}@9_[ݸҳ+JW>R1'{TXIQ$MBDpc-$F=+_3oWʺFI(tZbm&9ZG'tۀ?>1Ŏ޾u\}#hJv@PHilsNl1cHicL%; a 0W{*#>@rIMQ yFLtXn eEIĥj'WisߥculhrJ 7DTUbX ;iA7v CT^,l1QJwth*}΂N 材Eۧj-Ӓ("ޡګтL |j&= 823(`I٣t=u Kl8H $I n&T2()s$r+iMf 2;6#1N1A5h̚rzDP n%x9[HűU"u1i iA92mR`MV!5X``vaxRorHո V5f#ޘ=l8'R D}54Vc ?[fc"ZVf@'#z*T=~ڷWm\fRXʰI #-[&?_S*:kpI1CEoz5p='5 ֮*4 SUz[ڵH*f^iCVQ4~% kiRM[}0(xgןJ5ͰIEP2 ՘.k:Mfh=P=0g4N +*Y]Al4b՛"dsA0H ڃX)1EsWG5KNQ Zq (.6(#ha}hac!ؖoP8`H7'U9&"2~hI2sR;]f2DOޢ z6 F:ɠ;2ʁ#ފ`DCk؂:54ȃ=4f3e1ލ--Q&SAk"nLc/HY`wnS`&*gK 64Nh.kc+q~]b@c۠Eoxгp1IgE A*uokí?G|,ڎ5R8Ut^k1@NX>'h5 YHྡѪ s_C}kOؒxx/<]_xxjfg(8UǛ6ٷUiwam2c+Ls%8$8!ٰAPmcghеH'V G0V32{V.Ai yM[KDub~}OvP텏ORA|1kv?5sۀ<>ݸ*hWR 799}@C?7FfgoBA)xx0#521eH5r9Z_če33#bow4{v:ZbQ"zWYk|Ѵ]dEc]zWLE]p93T[U%5IQ,!9v sV3ZbHfH |VƙmNՔJ0'46$[ ?2YI0@VE[~A^ryލlL ޡaY?EӞĮ( A+ɡZgJѣeb jhVkݏ@8X`"(j.nnX(j- ՕBX>`MJm}LzTj`^DZ%-f=tTbNzpjqvfV9+wT-`Ns֔Xnu^d~"\A5 ;*nRn%I0*"L{,kLQ=jBK㨬 LR{Xvp( f瘀1UENZTF;VmOY в ZʭY/hʡ MӢ ~+pϤ&D'R0?g g4SD,Ž.fZL..KqQUz[@,%⻮&ؓ+yy75A/ʕqzdp.J+|M)[ /UO?GRc?V_}ٗA 8\s'޸:su6s׮7;F utV8rf.3P:eiS2:Z s'#]b-9'uqloiƺƯ :vϚ*T[ ԛk˺5 |+k8OA5$@{v}n wBU䞵 ]w5u0?ҷjıOƏm HP|SFr),[*wP3LX;Hѭx}ۊsIU`TU.?Lft$2ڳܱLbjpՍoy#?j4T8*p5v=ks[G/FE=[쏇x{j.0KJsv֗6@ zZVҰTS&ϱC9W'r=Ofi!*O5Xj1޳Ő@&!d3+Q{^H?ڱ[b Z'?N4igjn&M1E{@fDǚvFݳ9҂"hA& b\DѦ hvpIZEn0V3S[,X9Fh,lZH<Uɧ!f9*w`LJocrH ngWvLJP hw##1ִvހ^; cL-`m#$>< vṀGZ"Z4Xq]Q2U3̶H 5i[s϶KzHeҫn-Ȕm(+A#V0iI YfbWJ+^)-'\Xk!6!;u֨*dڹޅo=HQdYksIp{LwZJֹq6>+[4jK$=\Wxpnax3\܆;su›hLP3 \HA[ւM~Bth/eoUj.oV n#k4gVm?5ly !3jES|P$A4 @n#V؍'ֱ#w8 &=[ڌrBp:ug`G&(*,I#F7P H#4TY;D$pHnK.?z*.(DqitEW>=Zh=VJ+c*&LSmU1l;no"?Uͻrp15u -2tpEѸ5q5j*ctxk#Z ɫW֘濚{WG<t 1%k_Ux^y*]H9g=He3w܇3ֺs_EFX_cymVj~⭥hL:z7T=ab>\?S;g=qڣ񱩒 8+Qpkdc-11`{UСzf2 $/[:7;W(#^r`p*PZ*kUl+n y<ϥtť AHxzڢhcҼ= "lNy56'mNcQr-sQ]514I@4?( S'&Yk jr+poH19>G;\]G509rn3]yuklX'X\mH."j5KϪ:HYKR!(Xb(ڝL>3'nfcg ]a6 YD $;kM>⚬mVPK[B 6FLX@0A9]EvMvWi$'c PG&yGC?zo5#csT|GRBAl:瀧+uiU6EEWH尀2MdtexnØ2}ļ.E6[ O3}r&knyAvec^󆶎́'Um4-aW]4ޖg wu92bF,tRr|Zw> 4SMJ@azΕ9b8/|r^\}=> %.Lu=ue5AzMThfB$ [4U`c?x'Ke$j3E,<9=MinѺiG JJanٴdaVk#Qd If|DKUaKKvA aP W :01ۊVny&H}( CgjU*8ܡf2k1uœ`v#MA)XN*Thԝ6 b%AA-5 g5HtX~Mk)';ILLV ȪƧq&:5:͋&]'(ц3<4Q)6HV#Vt*-DH tX GcT c B>SҘ% ;Sl7%DOz֕!׮8j q$^kZ0a9GUjݛv'5gOh1ȫZշSZZSv*ӫl -۷UR h_+2ǚqƛ@I OiՖC VoKKgO 1ؖ7-45I\O?MUaCy7Qu`&xoUmZe@*pZ3Έą'V˻XHFQmrQ lQ+{m|1l(YU}":~+$~@hg'}>nmyω71gFYC<`x$ge[Y]% 9MZ[[f+Rsď/xn!7N ȜTq5en8cFiB֭n悭s\}OԨjH9+Kc- <@zמh BocV .?3Yķl6_v *Sg2 su=5޹ǵq7O6w8stkЀE9' xǙG[h02Vx^sA l?kq]sąAؚ0( #k0M>Zv's_@sk3b SsHL?z&W{b>kIQh7[DH>Lw_W}G˖7Ahj80#SHOz[ìM Py9~*8z>警 zO5Ӛ-&^rNvb Ӻ+1+jum~r&N$v,H0F#Xw>P2@ 8Mhܣ=Evd xL~h7ؽb,O˪[ ;T1 ӽV O Kb[i;zA?GjRhq'.ŎcV/K;oX# XӽŀG>aI#ЮL}bźyh2c#Ĉ@U+ڱrE j[%$:5/)ܞ-l0 Œ>$H U6[BISg5~ՁkaZmΙ@OZ9N`W9N.jv ۛ&+q);;lz+Hn%;*>٭%UFm+pFqS.ZPIa6Le@<NGXXP$X$5-+U{7W4fKGuV#ZmPZCZ640N(kt0u*qn[^qJb|@MF{TK{eZ-J)'5֬izUMO|Os|!{*jugTXXbj-5}?T- F3t^aa4șuzƙ,1Q J29c0k[ËfXH"LfJE)@&'*+5]h =8,-ۡFkcwOуu '$$QWmvڌO#?mʅzYݐ5QNx$Oz] Ym$jdyiٔri*dvGA9]i&Mc`A M%0J  jBrwnZK ;w~A5 㤊e-oR ۙT jTH5`EJtNYe*nťZ*v`ߏF<8SPUwAk+2ީ{Ap_zW"&9DWOKҲDtZVV"$W"]υ6-,!pں._i 6GOfW\2$H;+6{T3q cuMBOV){>}Y5f~A{jFergap1,G:x{q&~pM}_Ǒ}Qt5fn4/T^|qJ㫳$1zN3wx :=6wUHZ]!q01C'& 1Pś|9ڧho\;'hڠA*Cio,IѩkX*b6417m'F?z: n겖V<c}R Vw1t!_pm`4u&]_GTwbQL/[RQRgGhˌ%G;{TUIT2؈)Өb[ ĸ W9Zʱf#W1ճQqvABsFkqOoB7-hx0%ҀJn jE کPkbzv#na d| ! =C;[0㡦0X@ִC$\K8B>tN  A"f+RdYC@u'E=(hfМWz-1EU2G鄧$砪BqU!H#&B1UTmP3{S'iY4dj;(=GzhIȜ{1Br.MzҟO{jEC=+|/>׷}=ִkVlR{wھ?Q^]?5W=ڤE! kVŵ#1G^d"#D9]I.L@]׸4$gڍcF3z/1 \uW\:\Ǐt(^{X=9\q~-1'W5*G?HRJǹ~1aҵJZ6\PcjC5id_ԭ$ o*=փA;$12=+p7H1ă¶5JZuBfڥkm3ۥL/]cڂꚤrȃ(;znN3Y?5\!WFh333ց5@"[:س`RbG Ġ $QJOH>}PI,F?#Bޜ O)!xj>'7mҲ+kLs$V*5{&{V' ՅΙڦEbS&*qV!`=5=xߵ@a.i 5 *LYHƠ[dLNXpoJ۵óaac ѸOn+Vs0YPs0*{Gj~nzѕC0@EKКڄ2MW)eiI\seGQ_?9j‚ҿ1_o_GSG}$\^mϹDm:J\Lb5|w-[/M|>B7y`ڽ^NG&:W{j~\x{WQҵj?n}JnC,`wadv9vZd"Go'ֺ/:K7Un9xȘD.Ԟ$GVb/E}':w|KXۨ`ڰ2IGޫ _k5.ڷA&yw`YAֲ:7YO?564׭1P5ZX-R"ueVi8ڳDՋzK2C:X@@d ^X#PKA{_/olrk`_{Iu(˙cUj/U?Ѹw`]FQ19'elr~C'TBAi^ƥPRƙf&EKb߉3E"@X3ڡ@ՎZʨ"汩Fiõcߚ4ΡqY, ʠNmy2㖃SQVm1*G Vxm` wm_i ( t={ -auvI3:G}YfNA3<$dwu"7K2~OZhwnڲ!E E=A,NPNDH։vdx>PZv= V9, qv4:Es I@5 @;y<&RG$P?,P>($9b6ݏMq0#*-С $; t Hh iQPNH"8 cs@e h}Q? !ݶ#ZZI:(|*-lYM""WvJj\Ҭc8T=_9{gkv >CEmYw]ctȪnDOx"=JKt5jm[V`tWYqt`qĉϸc)X%OFDF >}16.1+U/15?UWG^R1, Onw]9sU D`HS+dt2Cs]s^$m`zy:p?T ].LrHmьL׻~4!dsWS#j6!9>J浮@?qK4?ڨv!'j&w@RzC@F>Oz'MR^ynY6xKT5kݺgHnoRT,{|}f/hN:›(u+v~~hoh~_%Nǩ>bQ!?jK[C0Tau6( E#>洢8^OYTSdi#hK$w=M|@ܕ&D3T*_qĊ }m sAgky=f6, 3߽wr 5=vHWbdA̶ጞ 5̘b39c k͓nr wB{x[{ 1Z3#o A(#\Hvg`9ngF1I9*Bʗ3{wG3Zmݓ -%'`H5B:7X8hZTqXi)8@7 HLvEn4d[UPckP@Zm3 0lNݽb[d75f-{)1W=Iv /ں,z.e^_'盏 kovVـCI'"?#K1O_ʉ}/Ҽ#­H@fcoC\GޅH*Fh\jH2ǒն(Mn*rh3N`H_.ykr7 X]dsA6'?1N&Ҿd ;ADU괠>qV8;d٠L84 Bj M) A$U[Q  ]]ՒztIdU{>zա}k ҹ$WȠeQZ#ybpzѲ6IT07@Ec$A*71S|h1ԅV-D?8ifo Wۓ9\}LĞ#~zZ =??7hkō{|J-I`kNvA޹#zvZS\ןnU_'W´p"GO^x}Q5ŭ&X,uD]7cR+cqfku`[d$ :,s ,`Wet]CRD{W*(T$VcuG}K '_5zA5Z+tv6Rf&XEʈ$CJk buN#ҹ׹ bIxmEwf$D5uW#Mcs׽l|zujj|$״z.#u1gGpczߌyșɏJƶm\ jY6~2 ]0d=KW-xʐc^iO(:/ ժ Dxޚͭ-X0'Tr_P m\ 3R<{] '5qڍJ#wNfbõfva\#1F$șX^G_ ]{-e'&[EFQT.yiFFfv6=h1Nj76@ ->ՂՍ21Ohl1]TjD`#KMi %ڻHZ; ' Yk{OW"H_G3\0g^^[\+ [F3S*kqOUW~/D PI=z)'9@5H*[QvӵDCgrjBX,m 6WSFcBߍ6nvYQb&`c܃Xoh%.g~"(u:޲y\@!@ј"=h؂}[oPw"Fz-V*2(v!VN՟Z+?Q5 76PpQy=u|En71Z,r;ONAΥ/@+ɳ+Ej︂:(Ю HnqAQD(X9Ku (>CP q Ѹ:#6rhrسA=+\6 5w[N 0HQҫj7ChDYaUauct O^'QkDDu[#+x@V#8j Rx z% {91ĖP*1`u,2DgZzKlQ&wH --ĐXS>zj<_Kz߸?/ wdIh3$:W~sm Pz^|\>uI ճ[?x*[$P"Z˪i"+yP+DOu{Ic̸$@u-6ˈ)x7ol5LԫO=hE[+u[zU+n"k=%-]dr^ DW3KH ι <+|éHs)Èl-^V"wץZVt2H9 :x6?悖] fS'qaj31s޶%ᄯCTQsqz IdJs F Q2GlD#Օ H&bMOl*2NsAo,Ȏ $Z!sF^ =[yH7K+DYOz&yjnx4"8P֭beZBAGXW\54E kT8KA&IܨT{A|^Հiy38bPFDBsE,#YQLmWzV A E;(IY1"[ ݹSUm!a{h  sR̀[T^'ocڥq` ]F"#ޡKV̊ػUFk$G޲6='KN-]|w=(ŻVʩ&g֎qA996&2b}tG^jTnݴmPZ$gC9{fcNqH֊;fgojB{WOqxreKO0k n>/mذ{ b3ߵ-eC$8ߨrH$54yyIpMsg F5ǧ^Xo7I^^T{N9}n%$^@6Kt>UP[?ֹѩoWE֐b6` Euu&˂I`cS{`0$W5AD5ƺ^j9%U2:+~p9|yykԹ5cjn߽Z`MR :89R 07U`]>zVH]&Ju +PmO/^_o5~٫'I5VXH3{ɖ[^:m]}0jXPZ g.DZR@'ژhĐ~ 0Bq+ /p MZSt2܊ʵe'*YklO\6r7qfNUe Y43a@uu:#xPPsq@x ց;j=#v uQŒ̭Q) &E ; nU=fnR k%fyxܫS:kX!@ `J$t5Ȳ9-1#5, [ȿ%ckG@h ﱸ?Y}@ k5KUyH %bf >ǃSh#߽M- ")5Ҿ&"`GsۭGLJ}1Mf[:] V1k mzb (4lYlm;PXRڌ5k@{w=?z'Q?zc`G֚^*uQkJI$֎ܹfʛI'cVň# JA 7|"$]1i-ϧ}qvƁ] {vMuVR}B8=?Qκ]GyD*[v@Z15Z71گTOgϿ eh?5sޔǮ; j.1o9OzT $E#^3@ fZ_sd94׵N OS[mn+Uj:3]LU6idX~ve:v:#ϼK}|I潲=UnX_ 1ڭ6"uiuѨ0ohLLI/ 5 u,rcX Mf*+5$=V?4m߭@] h _@PITnbݟsD?ݴ$N9o/lZ4[[pZ, m ?x&hWjjlQSC-sM:naΊ\M\l1RrIV2&'QFއX#i۷55Sꮑθ~̼Xb:ճ7GEUIܟԚrB0g9=K.ߥ[h-[ 'aj ebxUI$Ihg':I^#Q_v|fE6IsZOjc5edjoXX4JiՉyfdP Aʬے8R:@S`jiP 954`HQB#ffwm³Dr sz#o@O^;ե7X@swM0& )iXsm(7B bdf2 $֋A\fST> ~w8C '2Bnb>e0m&h,n ̎Œy_T| ?ڳkjĒxivpH3V.- ?5j*[5 `R.W!ERva/u z=-Z֘\s\l\2$-MR.޹ծ!T Msދi-P[UAٞcq21l֌Fq0Wn2Dgۑ@5#ނY Ƕ *" ;{[E]fjE(٭b8>=j6Z#?ѱ:uHmiH"1.v,=NcrͩBQq_so/[X#8$q5%q^:Q2:*kcz]*?sQҵRG.9][ =k@h_? oCk#$ZuM9t2 *,T\Xi\Z;z35JnyKE6D L:WkU$+et+"*k ,I{? ֤cMf}^yň$@8P}L*=->ƩJ ` hC5z3rlOz"o v߈C6Hbs]EK~/ 6+MH f{ m`@{7n$4("@j!A|Դ[NOzi1ɟڌ7&vzċwQ8 X+k@$ڍ p$ h`w&r ̰M\jģfDPA=T =Pg;">9 Vɩ11qv415 O6TǵRmDi:#N8PI`g3>*Y>+}fߖ'N gg]'1yÃU9E*y?(7 M0ӮDV]sIIԼe 91(V'tǥN֘ h"qBW(I( d-ˇr"zhQ\kf@(y?]frh `"1VPLjD-YufEdVq!k@nM`:^C>mH 0OԁsT 9k5;# v.s5κ,1s3pjo3|Ԋ6Ն{U 8BhVbeK/tbWHDj+qk(WI TE&[5pvϱlX:H)oM޳[(|T[  j.^E$(nѲ(aD挢 lĜjFOzjƕ)krݵWl9"ZM69qJ#l~Ϲ溸ͻknиf9kSW.^U)z棪֥G,uS~ǜxyн^k{0`b'sMtE"ʠ9T {ֳS&ѡ ܉E@#P}D KNc6ͲEqB:\9 d_5Iڧ VU 4 5HjqM>զy0ŘA9ϵ &ra[E/sO4'n`>A-Fb: M̒{ &bgj4u/F׵cڭ .e1j`遁EuY$OPP9Y՘Z›`C}V`5XRZ jd>Q6` D.AfP`UM'6@;j $-2!u9տVq:uӄ6(Ͻv#k*Y2Gn7SAQҳ3xnyj1P}ӳN!Iϫ#>o 2amȉ=>]OQs?Wnn)᠏~/9z-cMnC5u\|n8~؜^[޹Ћi 8޵LkX*USĬ}6Q3 ێs> DiN%D+J+,9ڢO_~NuwLIlcjobf& zӪoHF^=1 :[`:⦬q!w|\TQڂܘ#ނ73~(k wp``2yVZ= HU`AjOI̯~Eo&1YYm dTa Z,<40[h=b Vz1%i[k H{UpU\󻟵lmlsڵ JM ξ> mVZgb{f1LpbAM7;OBڿ}r͖[&0"MO"\]ΒÒGlsp6-V Bsߵ@ Ѿ aQҹp~ Y9 );F=Х&{pZt/xlʈt" {TVHT9n s۞jj,.H梺A.=,\t~tGQkvkWzOʮUm^}|#akyAf&8nFct5 mZy5QXbsZ b4\& h} nYOVjmo^BLo`>"X*N& њ|F MTr\ȗW:u$, Jh`=h +|A {*Qk7&Ly;=ҳ%oF"83SZߵO(itpwL5 cb#9SˆO)Dۿ5ЃH2GQFbI @hpU3Ex/ٷ & \GKh> q[zmlUȝ]Ss5Z_CvjYkr$[̙hHlcjNe=^ t"$GV`*ZnG4&IcҘ=p2! =A#qfL2y$R cV.2`bJeN#XU1,FO11: 0, Q{sL~ I<{ԋw;r}R4{bw?RFh~1 +5!w"AҢ0`dy;8  R6mıjĉ15A\Vkg7 :+ V5,1RV*&@RU@?-۱LJzDM]bEҸHZb>g8u0Q!]ҭknB94DtĜ۽RCKbȒ"ޗOe-l15#Wh85"F/$WY]tv3Ԛ:{-퓴eW2^ڢPu1F$:ʹlzSZ˥ӧ~?h5wQ+Duc<,{}p@=[ӏ6n2Xt1L5 krbOXX /k2ƪ3K͸bXGcȪFOCnwXeg=ˇO5BKH}{xq]A5=V]J^2xZ(;4E. }魔b[sdubIy sc3m@ni$z\athI Z?PǥE?GbIjȓ8@XY$DAonhdǀEcM DX=كo,(U:tvU`v-1ںW~ZS^<7[^ڒ׏^/Mn[+J⌾DF̰yUqgDyd^ǽ Tic?q&^J>ƂBGST\k2ۏG;S"ve9j#/|O )6Ï2*> |UTqQ'=+ߚ?v@\@zOU}MY96or?lTڿd*yXW\- 'Q,ㅮX0W;W/]oR[y'Ԣy-$f*| yksoغP&Qz֪޹CuGB]L1=jtS=+GAcps]$s确xhV 90\`ZLy5q޺+.X!F#TF9z}3yZjW0&0}+#TA#c;c{ ]cZgmKE\mT}5Djo,4Mf_ [ZiFmP)cPXS(y +Y[�).{ѺW[ 45 v^rTQj}0 `rr=/^!ǧւÒGz CF;`( jTz=\GbqM H<JV pGQ0]Ѫ9 jl(/3V)fڕ P DsҀl3@+!Aș1AbH?[F.DލL(Yy4OiU XY[hаwV&N?5-7RI-cBqLbzԭu`-sRյ.j+V՘j*=qnڻdq5:'cbϚۑڲn #ްMP4fO}%{F`%bŰELs[ݮ9eɫk PZ]g?gW­њvAU7\]6"+|_+2;_ {wmep3"~Oֶ>ި9[II9wբԈsɪf[~MmKhs"_Qlڮ* OX1$h#T780si)t-?ژmͻpO[Yee\frgֶUk+U,Lv=k$8z|zG4]:;f2ƴXN@v\p(-3ܝgAvލXSFGz`w,ˈXREDl8eGv^Gt_TͦPv56-MOJE.Ga8:^ډc0f>:}u5_Nl~fսpM4w3**kVݷ+lK`~ՉV«7SRҳM=¥#**G怮ls֍ Aemچ1 ҍL"AB6^k4 qFi/} 'WhMq+*Ŗ}Q]ex (Ӛ>6$dj$%r'S#$KE68D`Nk`0jhnN#d4{Ywd ?琪G$ )sf[hb; Tt!'0MqMKLvz 4Y=P9vFXNJ*'n.IoM -?j$6O^pk5i[b?jZ-NtbV$6sMN'j wSpս/mb՝0HzL^[#i\ked4f&05˧d93E&Xgq-I0~'Hhށ3y 0H~F\ۋj(ހO'5)<ȌDyKAf1Y+k.[ gQ#h޴;(ƲT9`FIzRxzƤSq3D޶sOG:jnv`ܰm=[fnj5W;CPkAܾ.G4fӐVpK4wYޓEwRdW+5J5xo/ʶ;8W?^~ >ni]|چ]=kώGjg=Qj3^,-$♬ Y${siM[d5AUHP5"}'tݶtJNu$%)3s㷎{W~yI@ E|O?ʹ7Ö}5oҶ,`Hk#z|oiwH=N#ؼ5!kNX;MMOVvo$C2' Z=4O= n"7ꟾ~+YO/|z3i љ&[T.@KKnoh/>§>M s55λ *5-Ws5Ƃ⹭O/l9HAQɀ&&8UkzsI faU6gP+C.;& \shlEܩ,N15qK+m`m=;KڭyWHʼec]bĉj39#so7Ij|@"8:b-g]% qZW面%.gXkvCǿ4jŻeGYD 3j *d&Zu `1 omR(B$$qR_̻l0g j Z'W&},h>/A4] agv\eA'q+xwlZӏ'5:y>"W2MōDf_m$()^}Tɞ0[oc$p( m ?w1$Fh$y1+5X%nm'jŘ<ȩ֜ zk?VH5x'5*ųlB`Jdo|b!Tɮm[YU - XXl`NEs_>kڴedEj 5ز*3ڥsi{ oR J$[ D4it4F КQU9$֤IyV&Gl$+}Fb{_RHɶSfK{{W,~sj7RzxTx߯l/^m(I ;~h%(i@8LKp_alU,[MۃrU<4=Bv1utBp \E]#+c%;vںȝZrr$o̹ZJFȍ>X jӉR3Lg]A+DM$Q%Q3D`lbbf,H'1H9`OdnMn ~V깱 L~~k *;wj!us$@,X+@U"s#4[V;ǚj(w1\ )B䱖1RFI@#XZgH Kj~,~l; Asw~ 8Z%VZ^K~62GڧSG>ZE' }־N@e;A?a}.([hd%j(QF̋n(Ex#4ESڂLq=;PTfwu[ blp;|ف53K<XĮ'u-?~(ȫ|HetCtJ#>NJY`W]yw%I[j:ՋK7'Fw'v[<2)=f"Z]J"lh#b X#׫=r#58 pAWwI[}RA^spIhPOꩢ)pDbO*CFXjO1FEMzhb7. Imi#bp[/+Fs.F?j7PmclC{ZbLB#(uZc $y4li'=0Kn#jcKnN [,d %\GV_ZjYڛڥgP$0LUHiY{=fo/v{W> fQv?׳u畩cMe<'w ?^^b@Y._0[mo'<~|x&X`Tt:ASc@][=qQY[kB⩺n%h2#jJUݜpM [;@2Gɬ*, 7.-ğ>𹹫D>kwm{RD,@L|N}_@}#TTN#+~?ۼ=<kY 5/d\V`(ns^iU<+R9ޤs.#z`x' {b5 >˜셋x±L5x'8ۮ:'Zfl{VZC_#ղpqSZڱDs/%2Yy< ָ4\lcԠVfbE^%a'ͫOsdkPh&,;vcUK^ka$b264W/ȴ`ޮ!^A]cejaR:MuL/fpP#+jOS7ozԌ3Cn֥~~Q_*RGV2j:'Ӏ1;6OsA%]J=Gz0 Gz`ǵH] $t8tcLP\ L(d|jT*2h $dњt7iFm4ɨntZ+7VU'v}S[d⢩1ҰULB<}1ı94. Ü cy4T[ ^zԃٶ é4nl[/ zTcOj'.:5pOCW͵;e:H0sPѴՁөlh۴vk5ELjfYǹ?Cqbcl/)TPϽs,`5X},n1S 5-+{sR-[&q= 526-&Z ȓ@ZclE" 6)y5 ^1=h&|I.͸I$.;n sVРgkcGN@RM9m;\c=fOqڶWcwxrC?ay?5^$ʊa$[#whZhYް-*;.k*0M1ZSV 'thq zZ;N ʭnx94Rbb®!LB6mtz Vmz~ 4k'n q5wN tVb8 봞GmYCO‖R t4}@HwL޳o2F=HNEPryPLI9( BD0q/x]ޥ*[5y\lFzV<6&ٌMy_hx||I*'gLz_T&).$CN${WC2GvݹXXϷϿS}byob%:ߓe8$c޽yTu>OJW|=ihi99 :|<>i|_'_YdbOz'Ȗ}S7K8A+?Sǭ^\'q&H.po+ cX=n@Df3|_+L-\aJ5Ǔx| B+ji<et1TtɎWho ۈ;9k5oǐ?j wB^ Y!E 5b~q7@GMkc(m!qD}R(˘҂֝ACQVzdĤ@ ~Er07mmmq5p3&k~[Ҡ=+FO 8Ie|5wc)h3t0X<j9M} Y˞=V`# [_Ȧvk-ɟQV7QnNDk0413ڥGG@V\VJh'Ƿ5A'։iZL߸En8@b@mx"J$ PJ srLm^n ڀw5  YP n_՛p?5q6o9V'?Q#9ʹ/Xa^Φ& LyC(Y0[:*'歅X4fڒ LڌI ޠ9Z$HelvX h+PKNEn\'M0 h)A+w]OckYfb4!RըE= =hڒ4 CmW5@L'1]1.CdmF;sü&Q WI$slfxO.ѥQ1_G-y:H@燛/ m wIDԽv"Kxet]jtmxFd⾧TaQz_>q3VH"lKHs:HHyb{oObj5xMW۫ KVxKݟp=~+'o amB\?ŵ|^YWC,̭?kxA¬3޻syLyn4_i3^ג+꾠oE\jO>0~gYy?3o~s\.bƲ. t]r;׫-⛊` wbŭ]Mʼn=pP`дn{D]Pd+kWK{wmoDZ>ֽhR6/pd#5k>9&Hh# u83V}y@@P:{^ jV2KŊ[`$;xμ_|k.Pn ɮɑ+ ] Yzt<θw WV2rZ >k\7]v[@Zg<Ҍ[ ;*ql?4eE2jw=F%PY8Ĕ映u3;LYVȈj ڊbr~*"ݹ yqי 0( ZI̟zQ*DoѰ4RҐc5 ](}kpgj\}G`G6c#*TBa?(Hpɀ34 ߘC)5PnFV"mޡ2R:w3ZʝG߭ jkb֏-ާTH$sS˴&CSڹՍa\XYDڡc\]6v ̊2('@sJqQ;$=h7/-]@14Cf{#"q "#i&d=S i< ~}T1#jŴ1mIH㚸=+Si'գ7ꅴ%}Cwmy|#xڢO\~}cyg }V42cO+U9(љ͑[4\-"O~D~j`; @b*ElhᶐF[5W;t .̰;L`I\K}_L#ڻJXu7ED w6D[.I1h?Ձ`dNgYZP E D?̊$a#*ܴ` jD8eBݓQǵː Z6&9&ݙ2k5P)-QNVV*=gFx"F {DȬO }G-dssWfv=Sju%+H0O۹b.{xf4 LD:cŵxj{e`l~ -e;w0")$duA|〈4r"; PY5Pt= 1,Innҍ92zځd`PzfEʉnI#UQI;-AvO4J oZ*A'恝 #O;r?p>5/}#sk7E,'&CV&f'nXs"#:*4NдIk왟aR qJbqG?&jDt\gcPd\:vZ+w$sV-/C2I3ѕpcj+WO0׊M\;WcFX0loJkGG`+h=8GOҵA_Ҫ\7 .8|A\yYVA9s@kklJ=ES*cUe܁&Ĥ5L5ƹLա%ܲ[Z)gzKG"޺Hke[1tķ4!u]#5q-z5;Yu@ DZ; }laԨv9G'(AAVj i&%Ic,Z dQaq3*ݟRѿms_~U^Xu VMCCIMy#kdk8+Y 11֌ܖ'憢*WUg.) odVSj5QC%I'5qK_rߗ& ]9sSB\ kyzsRA^}ݷI G:`T`#plX'[8t!Hak0yh&iJCIHk~'+۹hB ܲztpe;F*өb:Q\>Y] GJ2n(,+ր7挩$d+Fg5nbG M& U2 fŐly}&;u-Br0df^/'>IW`L@O{x[@"zӊߛQ_P5?KuhV1`seb$FfU/0&W:ky+ՙs^?V>U{ޓ:ME^_GYA؜D{^NrIXzUZHP->:_dV/vֶ%KøO_R |&π8d;mb=%Fחuy1O߶mۀGz?O*x[[ӭgr@A& >8__6y2|Wѱ]Xz-<)yOg޳mE5.Rr72fhrH`{l/·F'm.@#ڌ`W"si-F(X ^EzzMW?`~j4ˠ:ū~fCsS} \!Cd{T]ӟAZUrY 2 ڹ; %%Aŀ=SAn֤BNivHFjϔm?`1Ͻ3f,*iɣ Ry .H1ڶaBZ3\h r14[iKDEKIچ嶉=u-=D-i%2õh͆&Mo st180@4['Ƶ>^g $ pu<ǵV A^\֦Vv/3bezMb-_kf`߭XuԻHp|D~dGZ|8{^K=( F&D%tX$z沬pz?ҸQuw9BՐwA]M+:f)e,m"s5-^]7 +MFP*9.Zڈ@O$pVX@a&Ts(~㬐>ưg5 Vnĕ5Zg?ɕ=xu~h}:M)TҺȆ@vsiN~ tζF ' 1UR3(u;Tm#1U: { {FH5ȍNc8SkYw/Kf&}j-Qin&ݎ#Ni;Ѣ*&S-U'>dLx+q# $b+ڀqfiXv3e(%y @DA`:Wcl9T[hfrX9%:UXԯZ޺ND5B-kvn#u]#G:=ԀM83VmIJq GJ`>t*|WaDfAQ(ڣz7 4`Ƞ_ 9I  2;P n."#@;aҠRy9 b mך[j3<qڶISkjT%LOww#~Yv>;2I??j^/z|ξVWcOq8oNAiD(^⽼^M;:dc]UP@f'Tojm!H5W$0*5*FuS\]1˞Y sk+Z.랫 sQ7 =Fq֠,g''TZ/_KңUu# S}L3 ӬJֵ$S>u ҊG+孳#?l53#xۇxiyV\חpIRG;ҽq\oJͫghNxߵ*pUu.DY]c{NhnqG)~'/oonCPڳ9ז:_ =WI5Wd#=V9uRv@k5R <k+[7m?uZɻ,T$s]$rv #gܐ kmX=sYG]rf#`o9.KX"X:ýX6-]ds2dUW=◷34GSrkтFg ^֠P9-B0!Db.Ilڲ?T1P` 5"%ߥ/P)f$P  &1#vۜ8;T54);VZ Esk)pYXfjThF֘4n39295GrG?+zDH>FvSmuHlZoK+V|z{dd&]X#=Ej&Po[lfKqfXjj[ldXim=@8 DS[yu&KsqC[UfvɘYJ֭CpP"ӁRXIuPG$.L>Zե$E.H+S!YH+I&¢2ȠZ T[qA;jV  `=,6gQ-¬wP$'Mn=TfX H}V'E[nU"VCmXQzFwPyz뚍s)!Mݢ@Mt㟷>>k39f<|wukEn jJcS|1'驪 tH%a#5afvLQ 'h%I%Fհַ-% HkضmTPYd+eEIuͯ ]eN5tڿ4ODYϤa8RZ.\B'ډZZVKh{l$PHUhz@'i"7YFC] 7$uSvp##n+jސXMFIˇpxԷFvcjmDfRON~Z u DLcSob؋@>#b'pqzH^lv q(@sځ۰Z6ݿ.da"cLf ǥ15b1TIqP~sb1qY[Bi9=TTz߼ &H>Ƴq2=(+f ph,HnjaFڈEn}]##Ů[cwT.މۈޖ! Kt\ߥP"+9+$(ū n 3ȞHqȗ-=ہA\TMtsfeE,Cyu}8"Tv5q;v ?b-"s>@KEa`Wځ^ lKu% OQX+8"R>^Nlht Oa&ocNX-nHJ6*hwu.mRB;VFE v=:c?_D'Jz\~G9 7|@q"P:c:9yqVE;FC5Un6+uW]QjPB,n+\N*uXfmX?vkW^Ns?7m^db:@b߷䏠ڴ;m`p~GzOpS5Vv7AⶺOG_ VusW-J#$~vN1ǵb-T7c~;Cq'm<dPv"`$ҲDRX**BMҺ һq<yw;:jm ^{zӶ#35ޙм6zw;s֏63xӻ]bj7|L~({WNchogkKï+YR0ƒ)cTV Yr7QW ۻsze߸,=&HX>"wzdX~ 2u1q 79ԝAij zֵyUH_TH( 5!q@! E>nO恜 EA+pE9ꃻ408eRg= bpM`Qrm85ZYWj.!suz4|qY@( r{V T #(Q*b*{܂EgmHhQfr4ޠbƽ*FF-׉XR0cRNKA{`8`DMj19n1*qOjU9qҥN;q5KTh9Lb勢0}mP5&A59x+XPKSrJDUQ#jdO1AamqY7O4l=+"u% )'T.;rjWH2OTbxT\:iI[9G& YagrG<]c>["1޽\pwۊ&ffx5<ֹ]pu͗$UnjQ-9bhsA#` 55m5֡N::`Tՠ(b]@ް[!5XfP$@V*&OJPnwDvRΞ)^bA'$ZU5Z3z6'wZc[?gW:9ǯHMZioӞІP f<ePIc0*u.]-[zϰKr9Q(n0CkLORiF#v%5EpLm4NfciTBjn X3֤.xsh !ڧ.iJ;IM1ǵl AqS958{R1$480J Ԟ,޷6m$*A^ {V*lsn2,E^q. CzZcjBGi\MRZ:G+Hn |ʜlio%d~W;mW:a[RVP%GOD uްU&`89BߨkkK[v=9QwtnR""ŭi퀀NsU#0Du*]S(d|C ܊q'筑2:HoN#⦮(ރ DsuJGrd4npzVUX9PYvVqbG.5H3[dA"fqC>PF㻬G4rbLM_r&Tvj!=i\dֳCuR =WRY̚N CM~ySz1p\$kW,'kc46zUO="?[f/+q{/zg8rL]uZհ3RTɜHjJB 9j(f MI QQJ$}ԸlT.EDǘ~~ i r{S1]s7r n<]wzN]` XPXJpk}>oO]&ݶǛul1;&|%+^*cL54k6A/Z"Dq>•^RX:F>ZmsҹޛWP;e@nYcrZzvt~ˑ&rfjzt^mUOR]$@fȣS%QqgN/e&*uAM\\3$Tk1QsVV%A7\jo^m,uqϬ?I`wc4z-[ʓ3t$W^3{Y||כ:&3YgtֹTL`XD_J3ҲF# &Yܽq@BW=U<7XH#&x'zu{b@ǽu[JOQu!xZf9Q~.*y?R-] ` ~6rtH$&kbR'Mnǐ]?Uqv溹sSc#SNYBQfRfh轫m6h<_T.[dW:PU ]dkujgx9W3'iyu?8/(ZX!q`A3ZsP >5F¦rAԈP|։mc9P.ҏZp8?@{n7AX"8ʏ9zVҧZK~[2E@tQւ;qA4`gց\RXP$vO=mjݗ ku=~ "+$ո*]u;?5t6TěAHVG~7.[ + ):]iᛀjdXU LlW aOF;q*ܶF0i["i(b!q O41Q㯽 i/!(cF<{Qw&+>:dGopTi[sCKic4K[D0݃W{'f3VV=i ڷi1ҘlnD@ [gBFi19&jKJ@ VgZ-x H1=jƞ\oyaFjb+(zJдqPn[;'~ktVK0IZS$(\b{ >ڣYZ/ml!wf5ksK *= $\5;mȸ?M'ONwL)iouI=_@,ps4Դ4-r6Uik r;V5y[2DQ$d vf癠Y9$&~ոA&Bki%\ic#U y=( ˶Aށ$Tl-vՉ6OfP2g!'+`wR7Oza1$qP}-\LbuU0h#'+:la_*z}:Ǒ}k - $rs'ߚFjLwr$%vAt*Tn{%V &иb[qC&M+j^bԦIt D}#=h/iq9Y[$X0uzN$W%]hT`e+cu'arc:T f!g?Ir0TuQRe3n=Ek(3FP ꖡD2_~1nbmxr8׭{<|Ƒ`y*-OYAk4s7l O*-[UggW6<3 k-i^!kn%m?OpdLFYԲ+zd/SAndMBZPb`,k-^.:l Z)G1Vś:VsR\HpG"İ;UE@=(*vHA#Unj tj.I$q+XLmn`TDH`W.m\ ة2Ah7jγ. Ɋ\8nkrGD|WXL, s]QBS:T[qݑۥ1i P‰iMӘFKEDDj502آV-D"۶Z6ލ&: v0Z]w)sRP̃5ӏ]Mr|K;vy^ ?+]}>Th<#!I|_|o/߳e E{9G[z\:I,آOuz.26|f5;]$e]6wq\K/kr1 KA;ҽYl6ʶnfczt]fv:害7$4jU$vHzjR *mVe*[PHr ³JjU^9sދ[wj$-}&B63O?8?kvZa$uέeH{b9>uhn GLhHށ)T,X (FJn*TM;@5έam1(ϧVpXR͵Y ehaNՂв zTAAsXջa}hZ'jpƚx2Y$V Q8h TQI:QsqQ54k%gߠ2:|$@X nmEh ?jyځncgP(3 4T ɠClQ#{q8{,!F`u ye[lZݍxesVDzJR<[Pcn/>ִQ:S7]u(%$A8IvG_j;1+N_k{L(X?O/b9Ϙ1(־a.c;ꅻJ.95Z zǠ@޵5vǞ=Q+`m=opsl\ @.ʹ ޷E# y (O5c(!kZ+\0fwry͢$cRmP'ޱJтq55LQ pP=^ 9>Jo80J5XZM>@P~s+OgD֘5眮7$}QY_ O2#+bkKE1W"ZiW5'q^ͳ>ⱺ_e-55N_]6m$*-S"El0?E[ʜڡJ;Afg2zV4+Wnu @83ҌЮ(Qwf" D -5kRgT W?lemi4?*\#H~ZGu p{ qG?n +HfL;3AV L`N[&d1$=&W=nv `U#Up{tIG*1һrTzIj#`pm5hHb'[{14Z h;Hǵ@ WrBA0$44P="sCLz?QEOi]Uy*x}\QR=+鏠]Edhk[Ǥ_jeB=Oy~M鿤 ImI"$fH{VͿ qh/ 2ȳpܓ?jjf7 XVF~Y0S33\u/XztKYDrr2/.p>j-^3)qHH8&kn{QjR渢3Ns\\uвEsE_ؘq?s_`QTN*-Vڀd4ēS o#21:a˕āMP$n!;d6 KYczA[N7*I#ڷO{h۰jFយ돹RuXn|Uk'%x] 'k˻>=uPx|_'$EF;V9ӑ=7AGkZ_ ^q械Uώ~{mMYmi<ːPz{ ύ̿o%Z2#WՀi)5ZXA1g9ZAYT\\LR4R ޥh I@k# WEK`V"M):AqԨ"$j؛6`q]]@ eA 13]uΡXa]PL(Si5̫!>{||2֡׮\$ FYuQh?9KSk}^V5[qbrO'ޫKvp`V}b&I#{[mČ֊93@3zqA HaGC\A%@ =K0 P1'VR.w^QUӿ=*JmXsj3JRP+ fh P[- $ZW4]^{U5y[]6BS 2+24ކFꑶsCT9Iњr07TZ fnU{d+4ME7@9p@z5s7C5W:{.nbꡕKWQ_Ak<_Tx>GYj^tnتv(ϵf^D%HK5h<ƖLܷ[? VSZicI@5c θSDvĜVp& *NzV"UaTq@rOz 2f~ #d 22P=+$Z;P@Z=?c2Tu-ByַZ-+ [VŶjDi#zycu֖s_~1ҶD7iTrKe] h!aQ[ʷSbۜ&IzEURv*5UT\@U6oRLwG)ll+,>o"NO(pL4Zq{KaР cui-z^ūzi=iDݦFX5 7p*<[z y `}e^5[ϧNg۩kI |o>ς;| ҿ+ߢH+=+㗽6lP$1Lչ^|f*Kæoc[]Z2`qS`0(#[Ozdh ؓ[:<Ѻ"~զ_T`lXb vY3Xb{Dٓ5P[ $Iƺ%a @"mN'3ZETD5L:ܖ<!z;pv8VzT^OLVē{d3Vxi`[\p(c)jHD,{ցB[3=S | $DRXzGfXBm͊E 3YyZGʈ&OK_nұގuyv8c:_ &FG5E[Ԅ߽5%Y2vj4y`1";VPy?j3C+!0ims(m;E4e(sz]j$$!>)A#ՠM zE0$rp˜Lޥ:u@pLUa^EU鞽k0kd)1I@U#ZFAP[Z[+Aη2x֬bQDԀi-ӊ]c$NJ jIt2f  "\rP[{->ڧ#ƾ5Z%wn$+{85Tn= ˸sAcKyf(]bެ8lhXeV[b(-ӷZVME sҵwqFb5F?lۚ4d TU,ȭZ*Z;sQDqx5ʪUR(rq.zAg* wp;&ٞIf+UKڑ'TT-\tpS*-v9֧ˆ$קWXx"WcvMjŘXg3&1٣- OZvcQT(&gn U (ΐȞ8 FZβ^"&4[i[l'֦ƏL{bR@$I{% rYUXHVT+pdU [KvP)=( 4eB*F+1ŹeW-pG?$GX jXhx\UVbI9Zl==gɖlWXMt ]cA]khS$tVğ׎( OL;fێ(pQ-VfvqqV_~>j ,=kuxy{Gi\qqs9^/y]CeUd~L|SC A0E)Ozkĵ4:a0%ɕ5tnb I59fj^b c?N3Sɮ6HM,#\umY.;A&`wI ~D_Qz\EoQ2GzV1u7Po=-^3u9EWW=XzOzTvQn5XpRIKq;m$jFypg-_'!Skk-b]dthJUo^x&Geh Dv5]zq]kԳ Sj뙜X<z.X|Q^'Q\"I&GO^6wߧ.Mu^dUo_Ws^q~Q`t}j @b>.y]ձn޻ciYOAY۲WKҼ=CqBo1B3[y=yvn6-IoǬ*sö)Wn[bO$jrӎՂGZ&FkP_N)M[?$A5X70gWYk-+y{]s#`G* 9SqA2'ThyOzEAՠɑFɻ#iNh< &7IQ5p=`7(<=ۤ~(5 rHފ%s9PM d:T̏j  dɭ` q@F}@b`.5*jXeLǸjx:JEŗ=⢪,-`+jƙBbT,;aj $ѱTď&Q'k4Fբ߫Rawb1Rͭ*5'*+[:+{Cصqp>Ϊ-ZuF+:)*kb! fkdh rv}Jc4(KqPc<޳|!R*I#v++gL 5FڙLm\$*{jIi(j$xRU-\E:tua#ۚ.7=Fj8Wiθ#s!ۘ#W{Әx}9r1uKG{tڢ[c O<03A@'=h"k- `ҧf(䙪Au"$S5sYݼds4TIWhYbt2kb /.HA+ 9jE[phޥZdy#*kV s>6"Ʈ&̠f uEsvb6#WHu>k<9J>qg&?TeA- Lb!\YY`Ma6$L5 En/=j@jtDdX$EhgMIRի$ z,yb ǵ[ LDgߚ0!HkbD:V$O8Y(` 5&ұhP'n15#aHojMXہeXʹcDHH,k砊.Xz'V);rn }muUg6GuIk57К~yn6}56n,ҫ5:hӉzSNYTB0k=yVJs c>^=kjX eYi?E -5L N+e)$3 zO.mJ$IUj+_SLJPf9&kE˱Ùeh!e{UT` [PG53C`sرEh{nyR''=(,jh`Sv;</P&0g4sDPvhH\nFY yXP1ڊM#sd6?4,~KU\F=*߾DLec4MFDۈֶD; T^Q8%^DH7D*;4*01D[gWXҩD3gvVBZclH aHނr`~VR/9'zOU-,,L?jIuo *YUfGx],@#FڵI,ɨ7ˡFO{+ҧ,mW}<̎îdVjL^{]axzkRT7~)5YNf"++ړ~e|Z`#c.sVj񗪼nTiMxLt^b[VȮX8Vv wAEL!qP>ۅUMtk Nz9z1`@R's['>b~+nkB՛՜1+}?> ˰1OWy庯:߽۟y/O}'i.%=} |wZ#xàXW~oLJGNώs3ݿm^bnhֺKSD"@5;ZךsC#Zu~"/[%W:˹ ̮c#5JJzzu ڤ *zJkO&dzuQmًI]d=+@nAW>_1}3qm"Kk1NZ__GeѽTO5k<lHDUs6zUpRTfQL^>nE۪d^`wzjj;l^5-֞Ui8jꇊ<,v*uڐOa]ys釫 k1h LWX-[Ĵ"֊?։غ*DG0{ ⒳;#d@E 9#ԿM.MmWv(p9P/ւ?#,`4jg?֊LZV "j[֊S?A^`|PXG4dQ5YfKD}遝X5d4U"JQf͙\KHJdխ'itZ95/CA-ՠ>*PAP LDh؃[H'Rӛ$'lX0 ]6ˊDr~:-%Z9Hd7 @>Rl`h)pj*hbqF6C;6'n9 w"r1":*10df~gV#X =;U@Xnvȭϩ`Q `~@Գh]uf/,9ک+M;YS!8kAh'f:fOz9rFF]\:!yFQ{z(ޘvbO=cǸ1U"4 b[ ѩ1 =J*hm>khb9 }eCJ QdrMRuyj@'X)zIUJOj+B9V"HƟo1jFy-m6$U>j*Е`UK]':f"Nz ؁,9j*ҫV:bWlqUP9+gO(eAy0NxToi<Bm ~h+_%vc"-Ab0 (t]~t!Ud~jtz_FuF:$?MOoE 5]n*j-o=bqQ%F@|c:}l6 \چdilRJ U>mYmt~BlU?l}ɢ}ZMheD nw*Ȋ1c`)={P+nʥ7zO5s-ؚ` IVIU\+MI$&c=+d`]sϽSAqA'  &D+r%MSh#tlDqߵ DNMnṽZwAv%WEEqu(rڽvF3HF U:6n4WK G +\9f( ~Nh\ލzVԊČIըhg,5L/0$HD^p$WHYG޺9WdWH`d]&`ARt1jhWH"f=`$8y5՝;}56`~XKR~H^~/q[WJa_?K^>] t MXX2 *(jGAQj`k5isI?5+]u n=\/Ko19faX^$c!DvEO 632#W+]dQmAdZ"km)rp:WUm^)j} T.NGQjQܤ(+CX$5"IP}5@6nT&X e Lkq l6՚6B&M`ml(0E`/"R h(##${{h4aw=?tQ?J֟DJ/qjz1!kZIǓTsy*ݏhbD`ǹo> |hv'}޵c`U2ѿؘn9YwofS\Vc/`Y$OSNXhgS3;w5]e2+^ԫsGIikiW+۬E 9 s/7mz Q s/ .r`5@KN덮{cs~5лOԹnԫ)g3kWG4mQƒ}~ZhEmp=li`z>(#N:kSMx'ڰOt QT'+Ec޺XҺ kGw̦$D|Uqc0hbbE[qg1hp=$Edeg=J͐@XHʊbdDqR Y@ 0=#bۅ( q( IMn 0ąXXPm0f HsFFyZʜ3ފ2 A~ 8@y ׂRT\2I4kG-$ ™9[%{ -YP犝n-" :X$2;U.[&yVe2*f疝GoRū$*jJ"/6B{4"Ab?z-=kbOf=XjZn9VZ f QkqzΔޡM%D Z$T=lPDf(S mT A]8[8QjĶ8=h'qKq* =(mDAjIEh+zZiK6LYm`5Ix5۞\/L=W0y#5۞5ˮ) {|\遨1W^>S0q;WYonE1*D5*k(*ui4б!ށ5چh I sA#5$حĬZW'߽/-ՅqF=VX`Z Ml![D=Un1*o'exZTq{EqrMZ݁߹L6>TlUgF!OO[. TZoɴi3]b[_SR֙Qڀ껛P)F%a /8Ym@Nh!Eی{Bt.0Eݖ*gwh0݃ߥn0-'&yAy p#S"~惎Av1ւ~oL{J +%ށn3A^X&[֥GHV(X`$F& 4=zM~au݀+ǽ"4hm[m ?+c*<2Tg'qilE ֥KQyL23T#&5QڭqUKߊzؐ6_sZV[ۧJ 2O^  @]ÿsr1MK0ӭ\%kXGm"X db&ْs۰ek/x sK]ҟN$t8ujǸ1[퍶{7Ǔ_+<o(W%[,m*T=eHW0HڢW9nތA /p2:sXxpPA=+q]IL ޹Z#Q(vKzzt/wIu7B>ic 65E8Y, /jvkp *uQP+VkQ,H'  Ia+qɬau5op b 1 KsFT^Y2h-3ȟ> HTޮ=008^3sxW|i#~o?^Nחf0g'k8ϧ:Z{(98m_+>`#BbC]f:t\`>uc]@GqsĝX(s&?ꯨKg~kr2j]jOQzWTA=ɬR+ ?ڼ5I ڼ@nָ#gukz S{b[Y ~I枩B;= 4`$.QOSNri[͈0:X[ Tؽ>O\$a{T"R> lM2aN=(#qٵXZUڱe7Lt"ֆeC$c~Z@`D*I[|hFi,kXOjM=`é~Χ[VtH]\X_(8TmM 3U+3j (#+Gi8ZhU( uS¬{"m-dPոBO4Rwx@Y+DPVDAf el\TTBzs@;WEP'YwPH"Rn"(sA$CnނnEƙ@21 ȠXc@;ꥁPN"%AmcTGzbbOS}m{Vz3јq x Q[L ,Z}U!<MX Y"gP$9/РwY2 }u\W>^$ _ps\]ӹ`TQY5P );hn{jz`-Z`C<֘5UHV/3ѕnzqUĸ֘fQ?ַRtmAV]{n :H kyvΨ;k35ƺ`` 3+TX=H\k\,@kLBg޺HP2{ף]Ug<תG Y.7u.F&jͤ ^{Z1O}PK\ls;֪LI}fr*+Uu #REj`=zsZbŔh=YBŨfLiA;tֵ&…AkH[2, ְ' ֟,P9w/ ğb?z1:nV1Xq;Y v뜂zH"U.p;SWa,p~I9(Pm!x" O=8+\UDvMTzy2jsV=jt 7LĂ" UL0s[1ҵ nIj;,7&U7?ԀȂ TM9aي<bJ˓?֡AH#jVxmuJ1jܴi{U}Vl?E}<پeBFW~Ǘ'z`qq ?X]ݛZUH [5UmS*vFTyOQk ]2B~MyM8W`x"Ozk]Veͤ: W#[kB}iOW";]1TH%GCE(;ܒ}xsN@ M#Nì)ԊX^jڳ_1nye:{DbgڂN"@Eb2ZA1ڰsoYȬRz^7rWu6NE\u^^rѺf`Oޯ{9ziݝ`dUH'E}<3^Fz;]$Eb\aYYj~+5Ah#jKOsq*¹~yב:NOy;B*̈́F Σj1?|7SƾsJ-2cj^8nK6rSQm2L5=^/ݸTF~>M˅Ax%r[^3:3264.{G58[8 gcuz|<ס'ڶI T R޺DPa lVrR}FXÉQڌњ1ݺztPw ީ Ҍ:rPԄ ڌ0~J;Oj&(Op>i&zp&=h".R PA0Oˣh;bAz` ϪZ&ؘbx5-Y"A& 5B"R. Q\ԶE";;Qr`ԉK4MeZ@$\)lZʨ-F kVMoin3MQZ#$U4Yvj*_K-< uQWd;1> hiMlts?5kd1*ZҶJz?4Rjvަ[Łiky=Ӌs8(ʞRTNVD d;˓j6\UHW82h.s$T7Nq1FPHDTJ'i c5T=8F:bރskD?p/$tEtpq3a`ZOXGqA@#4oŝ8)xS·n2T~17&50 J4 I#h5: M0BO A[ V[ m>{y+ nXc#?j֡u(" )tGR9-fյ{ ȜDVX#gP/ۓ0{apޞgW =1ʕL4ؕ Eh6P)*g*TYؑzY"vh5^_ κ@byn۰vQDſVW13l$DE'uE1IUȅ*5D-ht nKEtįnMtuj0 M@$H$3Fq,0@2r>"I3VURǐxs_ߢrpڪ?Tk-3#3Q\uZ_ TS 55:K^NjpXhk4>SMHeHV|'l2TI4R!dB.[Ց[~ktŇ+L *J YVdCDֶ ȃЂ2HթIZgT[hi= N8-"9:쭸``db-{z0[ @Gu: d+!ۊ ʯ#]?U)H@O݆2 2=txAQ$ Eѹl29'U.޶{Qo3#jVE؄A\ꐶV:+pGGz?Yo[v nSl~su<[57YR~&*zŭLsLEfZ+V1nuFT$b@k^K :avbzUc5( 5LiGZ H\2"SU LD Et坬@3UnWi$Z'cA;Œ&>kuoJ) nӶ Vm"`}g|ϓ{/^퀖j$g~.|rc/;;J<7^o/f2h.>oˮ֛m^w}<,[|wn}fr\3Sc1xUG=' Ɏw`Iߙ?W]de EN'pF̪ApE+ړqHeuT5yunڂH/\`7}m*U mwyU]rd)YhSrڑ'gi1bXsG5Fiu `:kӿ@xm66s,#?ȿoO^AkMQ'x_3D|K\mlLQc\7[PN0nH|btNТx櫘^w㶀cd^N7yW"Mzc"zN#BM˪bcj[hofQ0H5PaxqZ B}s FkjEF; l)p1A'#h!4i?RNd6'?-~B{P3̊ـGN|bd@$FY(Oz`u$=+q:F-?a3A 6i-V'Qyg&JݯTjȳnyYZ#ޥD$ԉ*MBAM"[Tn-6mOTQs͈zSV:aXH=+RՆe`'MV-ۆj*lrͱsHiEE\lh_mGsb~5q~ULjZ"CHRһޥ ٣uJsޱHX!AݓR.N>ʐLSb#LIW$;2  39$#}oI^A3_[1wKH2+q@k޸)ӥ0AZ,>ŠGxUTL$@.N'5#~kL?0(5gG5bI9jf"#[h؍0G$ IYӬEJQ]dV$qָ$-n|T,{RڂVpFqU$r":$ڷdv9UVgj|ihi4Sr'hjW|mO>q:so̸Z~}F|2T E0x}k7`{n9Ϩ4ѼFv`RןxyW$$ HEnיoo7~>7O: 7Eˌ;"GPGhuxFvx`wLZYLlȁ ϵP$O}\,ځgQA221P<ۺxېGJQ*0OjʪAz؃VpY`&$HLtI+Enjgk D 1ւ0O@ȅWV&2ܑSBFvzʑjD-3ZIT%r4QAT#ځ9 w C,AN(+g6gl `:s5@W=&6> 5clF@ EԆ|:#G$V (nQP|A\IuQ) mxY ԅp3 1gOx *⎐=A g15V\R,ZU&u&N^ ts 5q JrwenUV$ĞzWH,U0ڮ0ud@HRX# 5ni c :[09ճF<.=y0;WcչPr3Tk }Sތ GJVvIZqc1Ҫ9U!`q[(7I5$GU0brqޘKYSuP $Ҙwױf VU_MAޮ%[P8%Z:Rf#в+qڳ6e 75CyRD#׫^>c֙.+_^~<;J$>6jؼ(0|@LKE`kn[b>z5Ys[q^nsמ>)CZ#w^cnd\t-C^b`ZkQ,`kRgVBeuJǨH*c HX3VcdG,2hb0ɡqz֦[Mii ߞk!&ߖbtZ  ֑mF9l@4u=s/J۲ÂĐzo^O'r bƐڹnH A=l?9_tlxn(c5yME: C_ ~kX4~ׂ_5Dva,I{4 'vƼǴ]Vq+ˍy73G/7LxWG$lKTبM=w(C3&⦶,esq`!Q jW[03ZVxR$УOXnLE`x6mo58jDz+jn2!ڠXm I=ܵ#4傅9kzpbfkMR>3TŝLLG挭 #TV{BaDk:ն*mStX1ki9 XכCbT^ߏ-y<]d9ݪK0dISni f4V>xq& CBPfGjQ{K:鉵u4Lxy"Zb "-Y]6ۋ dfjºHDK l`UȋJNJv,3n24n9>2#`dt sdOZڱqH=)b-7\glR~( aݑA?a 61-_8~ꐸMcNTa4BNP Ɉ qv9n`zjlV1oGz ytJJQ˖$@P=Њ$8 շ]$K> 2*h02&2 oSk]+]d2H2kuغY% 7HlZե"n uN㷛]b(Qg~38֮`Lk!n*I ыZ8S"}3iF 'YeVΏCl*" k~@M4eggIymk0[m};5mDckmD@ԦUPqC~ XӵJzPVJ1F` mD*!bv7DW ^0;n-8!zUĘ+[B6 :jtwA= Vd}HioQ_?CFapGzun\&A9RA6'=3ZUDXy61'b c, @?N*1ȫ iZ9ֳoE =#DDҪO42G",vSOV43ZDY~h ϵk1^BTπI3k޾ .C˶6~x2{?=֌y 885>frڰmi{Oīk57>p?Eu멲Y3ZpJ2+9Xn<^^cxI-TgS,16HV%V46uL9zg3`lS7ܕ sR 3q@"EbOeTG&?MDvvڿY~kut%J~#ս\iȌg]k sԎčBa@&zTksW"rLߵk+QzH1jEޥ&408bPܚ1&&ؐQQ$2"+5'M`w9QXr#en'H}CP 1[Q-=q'g0p0?j腉4tYeYE blGzʵ#-RJ5!34X3eqѰKbDҋ 2(؅&zTӡIhڦ5*N 5X5r\iQL1Y>ꁶ:Tظl?j-k.z8j%i$rk(cnͪ15^]$qRONv}Ƞ=OOj Vj?k< þ'"3!8MAة*NhD2FzO*Dq֍zOj(۔5ezL &Tn\4i͇PXNS@NG"-]g(ej1$UHB/OuąxL"M`aMCG$~ո!܇ t֤+IYDn܁zimj.&F!5C t֞ŧ9hAmtWXi("&/kzBX#e CE2i̜-INM ӷi1X`=I--nX퓀y[۟udžmѭPR;I[Zu$0{{7i_9}}HKeȒ@,+ugk+f+&r`QGԿAB[K A*LizEPA c=V^2rjRqwq5 Rn7WmlLlM֦Q&O:H">k~l/?=>.ܞZ*4!3Ě PQ0, Hd0kYMsr.N$$#`%@5B>Lz'RNh Ϥ" }1h@!yA/KP38UL`K.z@Vj^ITxe9hYQWaKA2 P[j3r*-'* ;I&25I9!D3 ’dXݲAc7 S(Lw'D!7N9I(_nIO?޹voK%`8R:32A5P FEtjU]^M; =zHk'>bͻ8Tyn@ȫeZ>b#%6R#c@֮Ap'/HbP>€PeUmKCfu2zCdr=BgX[|]FNza.nD]=RjR V}BKG0kmxjM@bηa?i=ER+h7b'5CkPij՝ܢQk iT2 hB77w!F'1`]S0;ek Y\l#7n4PtA:'=OF7Ɏ:Զ+r7rOg^ԅv~ZhRqA&6jw2H7n `FkGY m^hy\'@nfGNjw)Vt m*"xZ1Xcm R[Mpq \k]9(X[ 5xֳzט@Ȉ3E1-=ӷB̄_)oV&۩#)? ސ">sYKƴK1`zf9:VpV5R3lĚ~POS?үZ}v0OI3xo'IK/bۄn`u_߃imiTA,w诡^\_zK2zuk]t;OqǵE-ˆi=jckfSsês6[U9~[ROYn&9Ս@W\bgW]d5[H0I"Z#絭޾djj SyJ3 8↣R :f7D3X8V7:|Q۵np>kyeGZm$ށ=X>%͢@1@GJjGsUyH' '+~:uw1PFG9׳|{=#9xfK%8Tkl)Z^b5 kށ%q[soa'ie*xA5%;r8n2??z*޼% x\85XXڴAw2h$ a&Ź0H3YXޥBRsϽeZ6QtZ۴$ I bcڰ0pI 9ASwcނÁMe8&Ql1d{ԴE h7@*0Vr*/OFE45e wx=:W6Ż[*t=ՋX.`O*l.e'X+0PgPH*pyTޕ փ!A敊zql Ԋ'Eh=KY ̂k4Bo1Gzi"sMJD nblX[PDj"ى_Ij O`UHQ& gZs\uS=59^_-wd׫~q-Xߚ1o'+j Xb 33U>N㻱5[3 ~c"eqy}E1CG]3sUիm \ugLdj+l" \JybE\B { #y'nȃߥhvp!zdbژ ˇ0?%b"jDJ9}]T[PԈ^L:l&D g4a0;M+ATKDb+=#6[d3ZO]#h  @Qrz5 "s2g9R-=*ںFOs(6f\,zwTY; = m]09KZ/ ?ڱ 6tκ}2޹U´=;'s @]"plq$VO#, T)w9<$i\( WpXkef}5-n  ?'Ki{XȢۊpU-hS5y^3gM:C;#0\uԞ:|[QuNI-] QRpdX=j1梫ji/-=땮9[s?UFP>]a˹c=#^^#_Ka|03^{]sRI6HK* kT1.+V?YhWUd{J)#:,d4AG5%pw{Mn `qNNs>dO^pPj$]2+0Zw_Fx>PA}]>/zGӾ5T0'x?=uxWl{ 5^6ΩWOl@^k`2>DԶ1oFVZj"`sPq\'.;uն-^~ҺQWQ{XK`f[?zcu)9?sLf[Dj(9ձ )'S)kf}Fyel7'0&xhzT&h Tځzc՚o ?f5q?FTFGY9 9$ N0Nj(&&I w퍤f+AYIDP2+]tOj 7dKMuI@G4O恲X(-Ar ta<SV4IKd8P*$*-Qߤ梭gGeJږle@?s_L6GNAūCjʥ'-as"=!V[p 銁Emg~h,I^jؒꥺ-.)Z^ԊֶErGNXjƚFMN?7k ^&c>֍ FN&)0}#j26f+QjrOcW]zWYkx'G\k}9Z|Jwzp ׫ggzcg\8$"91+jNYɞ~#MшhMFcVI1YH03Me{T&[Փ[-sW"uwMfpD֮HțV̴Ȁ*F ]$JH1%LxB.@Q:-[d1+M9 }VslA&Ix"dڂG3LP3sDU+ʬMP"Y5ԯ@޳|[n+(k>՚"T*u@9e`qւ6`Q wm =HZMϸZ$߭qSFbeUF4j\,`XG?X}?,$G?rt#fɁҌé$vPyR*ZAjƦiojU WXuD{+W 3Ң5-X}8{5`H4UVe*xU b'R0IY-DS&x=~Lś7`?C9oxwyip>H`H?z.85UhYp,>+?7~`m1:TjRS 2F*a]`H/58/ZfU'ڰX%%@PIA erEZO!G";Q5 ۛ'Af(;zcoHUvzV]O4fm5tuհcX;# 3=MʼP9`ĈF#9c1 `A 5ALH ;h{Q-ހQN3FboLK`r(9?5Anȑ I$ho[$jB`L0VL:bAXhxyp+j%:P_YZ }J`*ަ e6֡w "QV`ۇpO5AOs=*4;^PBIm61 `uEj6.(f's 2zVYT֮}V=D' vOe>QQO5w]KXն7ED$gSpb~j؝ 9UjBk*͠Z҆wq"ZU{dn`TU6ū WEfUjGURzV\l ۾m'ڶ \޳'P%T{vV| ϰ56 mݷ+C띍S d)Gf+\S}hZa *jiKǵj[m1j(r ZtrGso0F:՘7 d1cMM7*UK@]%vFh^TT9>Tb^۰X*ZA^)3N 9qXj<ŀGZ2=u: A5leF @?`|"zʧ $W~Rh%rٲ$U%F-ČpVڲX@=ݱ&q0e{ڮVb)!#3TF uPL]eF;ڿ}1 ;ףOA19W}<_mѨC+G*N]eF⣨k[ Մ:^n#¾ozrv5m;ڱeY,A^W||Q^eSNZ:mrMls[@|kcq-Dr^i-ƿ~稔o^k>qiqzyq]s3ZGj:hU{#b(RT b )R*p/zXəiЙ@mթBXApD{,({D)OڂLew ]'w(iq$ [<@6I4e@D$4HLHV".j-J4F P}'RS&3ަP& >Վ[n u A"$;I*C;$8 +nS$5QwH&j+Wwk,V;J$Bbв83zGxJ!cMlE6ՒcT^xW^xWQd5G:P??Pc`^Bn c\i#OmĨ5Z j+;V`zt3ߥ ւ~|*lanb"ڷn #t;P7ڙ="NWyOڵ Ui k vB3:*7=Rjp9't=#+Am*qToոzvqkIi9yS.z5jhPYg@`IF▶;OoڳLfk5D }Z/~'wp@?5ή1os/j;Tc9BmZuMn3/L g&J(Y``7Fw1E\ŻD[ʬISub F"zWO}+⤥t>ޓ5eo^3Yk1?iA@Lx_P2"g}xۘ׶ ɯ6cH4 -׵k]/>u 3]8>xMz] |2os<=dl_I[H6[`p;goМ)''W;W# sr9?Uי{u̫Pg>zxZNy:G5-ê# 5[؅0{ti7uG{"ˊBr;)Y3rs mTD>щ( oqx~mXsjۂM!fr)JݠN P,Onmos1nO A]raH1^<#>5T9hwݽ=Eh靝H2AڻI6W6:SX ERAa,޹Z#$ s=W^c_ӥg,ɂMyy3uIw,aGJwmzzt3;϶UWΣOS\"אkTziH\ q <Zkٵfj[ Sa Mmچs Sት{Oڸ?~ HL>>]n\KnQG'WKЕKq^Wfk#A:Uoղ k Ep2*{̷' ڠfݴCx YZ&ֱMrT;>Y>m!@Z:miC4z1$'QhW sR9+0;^ѪY; KeEjKh$q(jYeN>( Ef;(^^1IX+Fղ0N}'WYu^ 5.Ō+uxw͚ P=\5!`j)BW**ջQk#]%NcKr-B%ڲ3kz{o3+lѱ+t{6tիqk0(I\X[^ZZ0dx ǑUO.dz~*H(u)qP8Agr{{nD q>( OtBF%iǂ&ү"JQtpId$4Cn>sFe9IHYUXJOPEضAd0ߺXpG5 Pǡ4`Yawgw=(,IPLdvwXqG qv  LvGކ}O FNHނmwbzU[TXk`\ ޹UƖ ;21\5+WY5t!G ?YcZ 0T@ݱ⭥g&{|Q+v41֢]*=\B;A#tΛ[7m r$lsI7maxb[670a囬 ?s{/ mT;qh3bEyf" T4eZ6 kP&yl%& q$fG5ST I`p1" ':}`c`nHju|@fU'AhHshHb z0A&mEX{D"h!q A?n84 @ҡEfQ&O[ ѕөWfrIj5xUS6^fS*C3o@ }JUFwTG}鍏76H'WwR dB8퓕4SQen>*̶܎uP\% VQ}o9@ jQnnjBFU:[SPOXh2\6OQ"&18Κ|ۚ-~xG _m/aZ F-3*́[ CD` +(t r zgA[LBMco|D6cNx1h5*3IM-(XpH5w؊#3ڤr+X3V0_TsETZ &`Zhv5djoM;0j4S^kGP(d5p<776rfjUtLuzCtOŋќU1r-"{OTEh[b8hpPikc?]l1+1eTQܾ$txS' sfU ;)2Rxh xPcv1[Ÿv`8iDjjH8'zVR7OJF-iu-ci&zʎ[S>̂ϛ#wGV;ExYaٚwt#k8ygվ5jܵTұv]"y5:U6zwkV0}YOxQW}Uc G~>/;ּ#}φ6Qˆ1G޿g~ovMGJbܹiwn:F^or:Skq oYyTkwY!_ѵ9+džKl6 ku*^)A,@?J1mBdakmA rxnV=szyW-N^mncF-OJh$"rH'ߨhؤ֤+z&­ fOJ̊%m|։Yn0:f(ŷ#5dѨCsy[ HЙuXѰqi$gBBe&B[GS5A"m̃84Yb nBs6Bɏڰy$lZdpzU6W|Sj>l|bmn"Ֆyj44 *j}LTUE \)ePȮ6GYH"\G4)vyli8JS ?31SM\KSMI,ag*dOޥ v͋9)ڃdhA, D8 @`KLu4Va6쪈#1mB2Z`ڶ um?5q*wL{+:nJkuNJ۸,$i|[XI#px]dCvIfȊ\$08D$! xWkZ YF%&{+Fvv{"L!]#W +%)$ {9AǯcںcڲI]d@ <[4pVnU%$]ԓ2%fٶ,Q9bmq=bSi,c@Ih"=`"?"21iPIH zԈ~{jc6كoncQv =G*;sC |(#f31 ē 8UL3Ԝ ?s4i0'4i0qGZ\90bzVZ nךN ldTAZ%heM44yjt5. PIҁ;Pn("!i",5 CA D1$QU 8+\p*+4$w&4j0: TQ HVqQNE4Hxl@hVkpG#^q'orMWZQV0ܖ1]5+,OZV @ k5{tme_A1ܞQgk{Gm q\jZ$`oޛL;Q#Q ɠ,>év,+SFN&0 P73=+qP$M0 Eh2=E3)Ip$P1m;[ն&U ms֌ 2h &'9W5(3y w[_3 ,I%܀v[SuhZS.n  De)hEPN .}#1~-kպr*kg"vMMeClщڶKs=C Pm%jWh"P A0h]OQ4i-ÒTGJA$ E%^:bYXMT3́'ڿQ!6'g9[͸ACXWi \lbk(Xs #{XU2O95jSanu8kz9sYf!N c^k]#]wafw:}듬p zAH~bPqj-O3EEC7 fWӜ~{׵wKA4dCӂz2-a`)  8 Fk,X7LMlNΔ5$k <(] !ɠ `lc%/c:Ϳ"90n~xjB(*\at3A@ OZ3PDsٰ]p5]>·{Lh{'`4 n)w=@F-y>ոM]킛A,O=ѷoo恔*GIf j z簣c0L*`rs V NdPRQFwa~h5d bEJѰm'V$[*Aϱ]k$AMWfU)l1@o0{jj",M~:ɿYen=vğI}|ϑ^!0=/dd\WtI=5LM^= TлPTf\No҄3[0`I5I޻gla\8 {PZVVAڂZv^ 5@|O+KOMuP7Y[rV] bjV){jE6!e+qYM@AڥLCp<6ES !Qpb$T =GS׿yb|5->-xD$LV޿| SA޷䀤3#UnQ$nUBdOJư>%yvҶWZ nH )% ZפO@G[@3 ', njo 0⚌N׬xfKJ ݪu81u jqBq8}ԑOWvtLjFbN" ILq1}Tmn5kؘۚң d <#]H^ y{DSoĥfWOU RzFqv'sX[&s[jʗH_TsE+^O-VOTVnd&On J $ )ր#3X Jя'?MlWk7u-NCԙM+OsՋI&94ET*0a?:܏>\[K8E~qgk_+騾X)0O1_[=>LS ^-AkSq`(3jjXs9_Nb"#[5x!:1Z#3tsJ]%IhȻxb2IڼVg+?jkGsEZC'ډwz;MNGF++VZ03FO^k($Lm90 ~ήg~jZ~ҷMRp8ߧoc~Yϋwz1LWCjM=Y w3?ֺq^-+yAngעG n]s޲]qdj\Lj TWD$ jj1$S(PH$֤ۈ hN!ج @Og# -Kf2OނAzrI)ޔm ϱނL<P[HP4xQF(Lڂ<!A: ŋhzꙩPnŎL+(c$Tmo@zzG@.SC"\$,JHk`E55MTlꎸl_0 yڡqm\'MR HO55eN,\BZ cӭrgM4}6WsFoMmT3[o kʪK5fwz5xv?zM/dST ZCތEPMu%$+Aj pg"uf_vV6R25R&)(HnzMv60OʹF!}vD#4&`ȕ{țTRˮSz'\ok(%cn=G>lm;Oj7HeC$CE$G JB0 /p:{0HE{W 3V$X^W"'ycޡH" }*mZAX X#ށ{AV;T *$fd 7=V4[, Xй,u('B]- nh{{~_ k8FP\~՚އFҋVf&vzUJ:xaoiuλ_\w]6$luk}BTdtMs75쵽vv'w`\6ʅF @)k WS:Ґ"Yv mB#5:F\LڴMmRbߓ86 ]$pjDUA0p;"0΁c4 ,@hr26g?bsLo11F/ cU(wR;M1Aoj޾$sAYx[y:je! |5ORHH:MI.1֌1Jq<ݥ wh"c&KD4@& UDL;(+q w_Z[b憅}B[&e'9p{Y@0' T#Bv.A(,ٓ+\jFV X4.6ϽXQoS2\+PT^Po>pDhȑ0z1PCP dp+*܇2].vel,[I/63>\cyEma0Zbҡ&sAxtϛ?7[j5Z9nA3[*U&mP&"vUK;qbʡ dM XհDrhj[2O1FUp0zE=/#8+ N# g-mA!#V[|LA i.Ė'j-`z(k:3iʷ5nwB1sQj`zU& }_@_"/$mLհƆTtw8m`3MMa.Z&^Y]nm ebTj-DzA3U\sP&Iz,`4+&y5d~L|D4tӺykRUIiy3Q~h*-uV:=덮^px,}DK(6; v4e5VF'Z0*\ww ׺LֈuFA(} ab?5YRJ>dDvGSΘYDdb[h&OXMJG҉$"7YsZV՗Yʉ#'&Ak2iYiRY|.[:u'&87LUN7į'9>Ӽ+z$s~%p\kwKZV)}ӥyvNmH?U32cJ:n I`4Ɍ֋l0Ȣz-6˓HʺcTUv; 73#TJl<&;4"#v Vkd㨩-L 5:Դ|QVh91_ݬ*7`&O`>k^K7~toî4QwOA_9?7ߧxk)LvWKo,in*(3#sղ53ήF'xl1 )ktX^DtWon'y:{||֣=$O{9a_upn3gĘ=&L5C(p`MfYxAZ㑸7ScޫX.gh#'?7n e IdvnTwR62#ZVt9TG} e*eN=^)G{P ^?|O/4ځ>12Ey^7Z.;HA ?=tErی ]drC.t&ƹ}}y8V==MujFL!]bqD)Vb [d"+I%X U HF\I $H*sXq'A ??⭠ILvb oz zڱ\{lA$uPҴq.:E wc Hldw. 1 $> wZh 1PA\o "[k $~:iXj;{e~ rmny\T赥Q$wZ!ۭHDl7vc<ƥPYci=jt[t[62Av݀׃ jZisL%yz|'mby">"֦D-:{w5,hitΗ=kfxcwF*-^LuU ^8=MtX|@`q+q/{HXOżX i&rj(x0kkbSlWiYGr &D I#)9|vL WyÕcոuٍcNq[L+j4Gr&*$Jm`&$ؤhxo2 ƭl gT@/P4b#8(,%{#q;_Z[6? kun9kv9'<"-X'hn[ QZ jDnBC~h_H$v( jĚt!OJVf$ތ̺"жp`QkO9=ۼ̐O .3HO@MZ+C!`c[s@ LB`Fh#;GS@,3Jyk2GZ7OQH>90BIYQҊD3#p+[cCpU5,޹:6ŋ?tjRj6gEV|=??5ejq']_N-[YkѼ4dSj+-dIuM5f:1pbE^-G!DgO!ێjunRrl+jk+s¼Mm,F9>թuzKv" ]+TʳhrkHqQSK{тij&lc8ު$g2@Y#ށKd}6Lb( H8(+?V7tK,MjW~b*cAZݷ ڂ7K` h} 0K#=Z{a4'튤"븑0GQ@{am2c4Y;>jpǧ$jO@XR.Z?*j%浃*@^CIe$*a*$1@-K)AEU@gڍBZ&)a2 h!x00 {Vٗ'(5.9a"kKҰdb_5e@;+( 0zu n~_, '. ߓMHSe\qUUWVoL Skcžޭ>}OR螳$ǽyނt- |554 wꗉՍ-:H=el^GA⹺WnH8^kN6Cʑ2:ׁ-R(8^$A;wj ݂AҨ "Ds~;"a?tԱGcۧ.GŐ}Hz׋czu^,`px\XmP:\vCKn;}ugV`XOP6Z U_ >^363YLbjk3Qj⻹S\!mI?f\}2{@Qt2 iL*t$L#]/>klp9 ;}g_QOOmW']]ݴv76NxmTTSLck5mI**ZV$`~k!\-uͲ7fuӿ<OA^~v!:{8ƶs3^W3 Q==-RLJ?kQ.XV>\+cwI39ہ-V?&= Gz6 (xPҲN&dةH[~5ce$1Q[b vڼ~_Ƿ諛"g|_'ӽ:SjFk>sJ+$zxz *kqkp/ܑ=ƹ q]csw,ĴʇyJ<0RUb*"hye3P"KV*TTg≥(9&]m:\H4G,|Xl=jkOEb0|#hac#UOjhUFN ԩb$ yq07MKB(V{{U\jBcfrm3Ae MTI cSQImZJ[!T4TdI'z  YfNVhӕ[:q~OCڢ57N`n*!N~j6JXU{Tjg X\鉸z(]&t5gL/5!@z&F+(XqQ#S՝5 skOtKY?ڌR F3u7e;j`7$hw/=fI9~&6=fAkZߩ 1]g)*n\e鮳j2=&o;Z9sHS9q]]gWq{=pI9z8uvYPתpzZ;R$ȌLMBЄ_T8Z' +3A 7+dJoeXڷbrވ4EpDĤv;FE0TT54΍ցZ& h&@&$4m X#lACQu GwX#"AVAߊ&DYvX-( !{u- 55Q6㐠OaұsmwN"(*3@?5WJiN,y>i |lB#@+J ,ڂ$,# <ŜP@AAʪs㐥''sA.Xrfc0@$ӥf -i-3xۗ!.T1>u8c]d$W\9zW#XwYE}VUjOZ^bͭR2fZ ۠=*m pVOPb8&Vc8-Q QZQ kGVqxǠ}d{W,(k Lj<#_23D'9#kypϟ}d5ZWR f HFI*>k; }z ly8v㱹dO⼽W~\~kz9WY79ԗv-kQ%i"].K~ ED1C3m"FM H5đ|1+CȬv Ff 4uHݷUTb^7Օk'qJTVǢ}'z0:~/ns@~O~;˞%m \TNܐqڪ9םx—Cj:5ex bٓn1ZIDE&lHIoST2+XMJf<IPIY`sځy;x :u}KT ##k'@G@u@6jj6Ш*i8ۅfަ t?#ͅLhaXzy-*`v.ֆOb.DLR趦ݓxi 1(/|=xldTA|<^t*LLV%Q1h֎BmH]$c5UUBbriĶs=g^hD|Tbj`9Fh I 0Vvĉ'LbIY`դH{T6Π ~ kk98STR5*f3+=pnZ9FW3]$9&S}fm@k6@yrj[ߊs˗] I'+S*'?L5d2JvpզP'uW33M,R#K{D` DڟAkX2 hY'Uv`)ԘU1ɉ :fL|̀`wCC`n, znwLpIcژMi5 !YvL Aw Mm [#jD?8MW/!;G^P7D@l8TmPcz[I0AikDQ#BtwOU A $9w| j(+w=5(9V@fs*` /sɮt?MZB,|{Q~=J&n _4w7PGB?zyUY|fQG &<ׇp3t\I|_GuwbLbjn푚Uk]b+F2y֌H"Mn 35:^ښϫj|A u5:b H6=aS^$Ih3LAZ nf@k#ڟߤ4<,m=AG>jS1^/yۿfsIWg;G90{ןX~!|:8-D7u-6fޞˑ '];\ϋwŀ^N.W[}D(G_qEg_ʻDZQ"*5"a$Jw/lwsޅI A3ESFsڰH9 Hak-\ A%>f( (&NӂEeZūq8uQ}'R-Jߏy<_<5N~i9g%K6HuDH]rDmbD,`J("~WG6>z9陞Z|KA$~j$ۥsԎnIHϵ(`Lۏ$rAYX{D,6O5IAZDRYfDVŅQzvjYZ0c#Fz AOZ ҕX ['eݴ8k!,LqMI5*@j9hm 9$P>5m̳nѹѡkJFj֝W`w,;ԋVD@YE{V &wvWH_aq 9 -6=.8ݸFrq585 Hc5m4_l|x'V3Z](uT lXNV}1cu`V85մ6( }1RmVaiXeRmZӣ2NgYֶӖϴ >mj>רďiX:붕X\wx庖5J.-H?j9n oW]dM¨Au5FpI3]ET\I>]\0Vˆ^xp,=y˟]oVX޺\I-$ DZɑ]r2 \FmSzAp9U•`9e\b JWl]3TVSt2Y5X@keALbi7C"0$Ԓ7$Aj0#jN@m~PhCI$P #7jF!{u4=ˠU#ͱ3z- ebϵZE\5 X#hA# 'F7m鎔jNDj; -q$h7-~UY nG ,98T7oޠL+)&g۷ހqq9OH9A3R#8նDAI#  @,3ED[4ꊡuڂ qO~( r-p2x;Sm’:MQbrLޠ]rLf*+b=@EjȂAͱ;DK6m%wHTdz’xf5ڭA<沱xlV=R|i-9Q6=##vُN+D"7A= pP?Nj,Vj#k|0']XQVC }ւ*i&LPLrzQH&L`=()m$F,N6DA zH G+tU1fqZ31QI=(ARHm>$׮r-'?橱$If&M@(kqE`aR s$Z#Z Zve;G(5BN12=;IҀ6. r?()%4w1t!AvI2.ӺSrx٩b8MKT*m1=.9 g\+w51$G/㷏Q_]96H}>-#r?5cG}>+ c٬ƺ_0Wץ&}Ld,ca@#ڤfk-Y2c%A…ܦf[v:T,Qn $eIZ.UeUm7R P{%ہSlhA׽jRc+mwKeYX 0 Uh9rկ-`'kwSOҬ--[ZrO[9,OH44@GtK z]B\lt!bfUAjʬ6ҦF4М뚕i%0FsPOŻ Py޷YLF~Fr @w,^ftlY5iF+3=(!n ހ7,Jc{`~kSBeY7uUF@ &9Po^ Gtc[[zH+xf>7G_4*N#_io M3*G6[V& LX.[7 =O8+95rŠqD+]DeA2]cp쌫tކzEl扪n9$;_?F"ZpTiū6cҊִaM=> =[}(`LF0@QΌA @cB E`-&P.9fȸPDWKKWW;YCZ֖Ť&oAoFADѴ.}ٷvkkJR0ҶkMf[ %d1 m z|TԻ|Aᛤ+*O?.qLCR@`]6Zu XWEԚКbh"L醡 v~jo]/sy@r1UՇp$*tms5%g*p#PSwQրj$#n$g5Sɂh) ,RҜr$G̑7Pf='3( ۭXF ~(%rb&:utP4h{J2O`0$ ւ qc\$dqA&[A"LY08)0 jŴ${{QcqچܑA[#hA֩95^)2s&hcuP3; 0;A%[ nHZ zPFͫb\0*qJ7˰^ՍR7J8ޕv#xԳg"'lbat`ZAmIs?zyO#}kj;ŗj@a N$x75RX(,H~o }ֹ̻)ڲZEs\\ N84kMMĕwI~h6j-1FFFGŏO¹$bT " zZ;>+b3YK AUkR+eM``z uf0 JH#z|O5tXk`,zW|_-C1$t5^ZNdY\jXpc5t`-R \F1^.q5s$yv9W kw0uڏBgDe9``x@>p p3X-6׆=؍:\ePN>(%ruۥN3`LTydA&'Rk4R{9Z֐Q'Kc~RdadכW hfǸ>𼟯oSʁ[\%7)sRuk4.~הZ[y]p^2W%jzҬaRU9ftC7x{DڈIa!?҂bI/N( uH)*.2Fj5U'5( Ŕ@$Z T m$Jz̰b3PUl%ՕgKnB>խuHFfMk@zkcEdKZI*A[:[, Y^*Zh# R5G@Sմkqz5jƓj+ƳYVM+.QCOX26j%hVZ$:֢]Pr ~DAUZ`ufpK@=hp4[h1j5Z[Q9L44ƬnμG9 ^F@'޲hnHڧYkp/-NOZctGymzjSf[m"CW rޒîAol؞$hjVec(HNla 9IM @&ł .8.v 9& DQ^@rzԕ%I$qyRI1Ebq 3DԴUtAV{jڰWko0+*{h>[@tPD⍅RJm>rSޯ|Q\ LM43M c!#N ۉ=H_h7Q8bhgo5-p'VPW$9Uyu$>YWEW#q"yHm #eQ .p:0ĸ 捕pLѶhbJHhAf+ 4n & \Q8hY:4t~+u wm2@TQً+F~Ʀ*8*G9v/=GTo`Pgc4K]51ZI3(}9JJsT]x=jjM؂ չտܬ=(23ށ1\7ĭ38X8}J9kx!!W*_P?xMjDd5}njwvSp` Y <B/ր~歔 ϸP)*$t>ոmHڷmLb9='߭hL| LtۥD]u rzۼyfJִR`(|'nہ!nޭqGi?4 FyH4NOJSR8UT ւ6h!7C Ȫ3ޔ5 DC}mu<+W>3|63k^|ɐ+*ZqxDTA ߽M2MEڨYN"sAÆ=NSƢ{ȃv#@v.Wr3ҹWYL-NI m۱,sEBgXⱦ"MF{sCS`Rի r+КRjTOb,jLZp@yRX3n 5c:r7: J&{H Pا&jZM=hC]Dp*9iluh OA2('tA mZԋr Kn@=;b9x+#.(oRm*w~xe :AԖPS`0;L=dNv{u8?څv`29n>k>g>qO, dWI| 봉k$.Vn4@\" r ݽ9'*zi˕yGZ#)l#M buil*8;Dbtڝ{lhou,jHo;sUMCDH>a&zF(21IHjAڀ`?jnefy4F]# 7;qA_T.\!mIw psF4 r)7NXZ@9i ";9Zv9*$ WcFf#pưh*P#⍉ܸ͟9>(r=*R-DZ Icڂ-mbD}顔vwĝuwpGl8dQF7Nlj_s@+K'Mf~?g@j!œm 2qFGg}IMe &$ xuFǴ*FS5#1ŸjC`o tP޶K\nTrYu:c-LK=n|Ao޲FeoFHXX۳@[l@wNx}L0IǿSz?x2H$LcCbL5v7Zn IUAp+lt&5O#Ղ;(76hάdl3LO5Ս e gd9FT?4Hzo&@ށ{crnTTlG^Ab1(ːٞ`Hɠz ,V7"JϘN>jMȟ֌E.ŕ,EŊ9A3(u[珚M7mլ9$thFO6Ab{ t=h,#2I3N+Kl"DEMYrwzJԮъF[v Uu\Tb%IH-(aWD2PZY-+b ?<֦9,O ,GəF=ǃ{ nqzp`ɯoW[NGک;`jT ZӖj2zaUibNJ 3 k>r-@M3X{ 4DTwuU=`66TTrJUl" NqAq1,-. #j\!}Sތ KGeT#rf1ҁAzX@s6 jz+8^ކʪƸsʞʂYZƐ 1Ti(,@cjԍlo~*lRxiUBW+h;]tóE!`Bim^,zZmsDW30xn^#h '|'j."@q@LSqF`!]$+*zRoݜբNIs]#G6V;`&MkG[vV@i99}|k1տ5X'VMEq=ϽyNܼǕޛ9_'p`2ޝk^5<åstƹԻD 7AQ= nh9iS5YHN 6 3ni]RHfzdiZO+2?;%H@M" Te% {jq%}%PxۏI_k8WY|k/y;r:DKu6LMr:r^%zsspzזעW%An/oG, {מxk2xn+I1@-htE c-*t@b$ǽcq0`GqmJ3\fHPm^E ;,coz'VЇWXʮ=KR̅$Ȯ=ߦnEdA<<_[~fܙ= W=NKƴ1!DZXAOrӛ_`:׫C =WYP}Et-28WT@vȫ 3A;@SyX&!w> t5Q3LhERU/6Ѕ_n2ц SWmv1X`tZ*";}[\BpN'?`[V퍐9Yk{V`?4\-ϑb^N"Fil gMzm˓QwK.=;xg#p?5 t=`-HK?4{e{Lv55lFyѭjv ov&Nd Ĉ/${RsĕOUgV Y]A3T5U &|WMG5n^DÐxhߜuAA Y[RGIJ\AS9R G1/ ;h^)7-ۗn:;6T/:ny՚@nHk#Qp݂W$I?zsǞf Ojz$O#]1R[\*L+)Y?h+lUn$]ߤpjރ Lԃ}V$1R hX& lUE D`@R@$<`C{3Z\f=("ba4$ f \R@CZ$ 1 (ր7-$0j)^5Fts@+8=C`w4GY b`ߥN)NCA皖P bBbph $Yf 5˭[NvzH=hDFA*$vRvm'hѲ@%634ٶ%}S a9fsR{h%vM` è,$6r+BB*y'c,u>G $X<++M&z\k|+BR*? Ǵ,vivXNF7ln|էVՙPQꉷ{1ԩZb1Ñ: O5q6-#'5QX4D,'5)VQ+d=jd1h2Y$J.7\OJW=+Do& 2(FI('Uku e#5ijՂ0بfuD"@8!:[`f=TVAmcޘ&܉pA_[skq-:}L !{)+W6#Q3och_ lt'07bL0cBI AH".1V8;- _'a 3kSɣFӗ##4b[zh瘤SM;A3&3vJ3EprNTWj4l {Tdx?גn# k_Ko` ^{>@[#+Beޥ\d7@\@h2{%$0nxZ }GJ лzЩ,}ȣ+SZU޳ "9Uj(sUe-ցpn=h&0AEGx(yN~(.\binj͙($˓ Ğ @:n#wjS2 Z@3VwR+`i?Wŋ!Iq~/2mϥOZbq! #uH38V* dԵ%ڊ L~j\Uvɞ"A8<eyhu,*ҭ-Eqު%VW1UͽI!jE b03:3/3I wBEetu]܀mLW}@.Y$`}N{ 'ՊI@X;fj4DȒMo㹄1D+2"hʨBIHOa<<"7P(+rLՉn${ G[Ҫ-&Ghؕ[P'L.nv)Dg"aTsXHo߶ۘ2q1_C>kۼ O|nshޱȎ+cǒ7H8ڷi]>oo>27O=k^5,=S\".+ ĞEr>p}]LGN }r"a Ě92(Q#ҍ rgdHY=p#q֤1 @6q@ j(%kcwg}1>z<_G%|_f+y;kLciϵz+U5˯r@y{ሑky)c+kW.凬܎]c 3hYH"zZ afH_g˟N7>P^c\γR#q$]\>3W ` L͹D$6@ Z c6c5 ⱂ $ތE2[WIq*JɭMq]#)דޮFS3c5`ߒaf;Aݸ^.B]I*,R jRjEo$'55mi cSj.0;tX,֥Pq` \TKFK9?ehx~͸ )ܱ%I53YG4nh{oAR/y.db# poA{،M-F3ך cV c.H`~+R/] 91fbe3AYuHaJؓ4X'&.0QXgՅc A:*:Ջuuь뚼6瞜ɣU^vOb֏T94f43ǒ#1{c94x=0Q=M͌Vyqip:nXCAX {ICYVT<"2Dw^MSH[5Ha+DI&d~j@01XV=B$ԇkl w3'$+((m  >A$QVt:&d 71pYDʃ?bsM*[Z'.26;oV杄IEF-_A nK7CGyLղF2gZ{ \TV$'1gƭ5v12>ba~#mX >AZ+"}E\~. D.z{6ANfR r^D#ȁ,.TgHO~h2 lHzP3n.nAH 1T+ݶ/8#y(D1Xm=YaO[›W7 f4 nDp  y͂zvnr (.LPc `Lf"Id+ 6'=H4h406 $E (ҪM+^l ev5RAzں80`zfa0oO1(^ ކ llڵ%$nS; B'ނ[2 et qnPTxվ! b`{c$yzC@̲Cp" m&eLj53E`sF4<'Rl]&$`7Wje$Hm]MzufJD3/]أrzt+ kB@iTHdq=Oj0kmȨ`8Qr@i]C>j -RYO'ղ͹ʼnX@jҹisVKjwAf]TpNc<֋vM=&+VKwmP[ipP\QN'>jcN6ǸW dK L'n .vT"H6@IM@-+.h)F3&oB}$b!x"ڴϺzU*I~آ>`0x+:=Gz]IK!C]- f(k dF3nZbS@0i 33TfBz+\_,`InZ\ 6[Y@k!P *Oz]#>ӥTQC}@5RL hڼjBpA[ՖnHT^8`i"$3W.}'ԩHzW^^ufW0rq??|"l*G" ף\da[UACsj?c>[ne|<ն3 ׮W%+r$f:qR5#1ץMt -1428s0;0ScDtI( E@FqiT@8X ѡhtKo5Z<TC kǰ}-"gk<N"c[b= txa@Gbӱ$F:כcĮ30~+˜+yၜfWxvP+*vX)|&A#+f ^!w73@hwb&HJ"? ؆v$V15$bZZ~kS$ 6sjݖr"kKS]j赴۸t#Wӯq_Nni-+ ־WNMcuy+٬o2ה}VZ"9W^\y,$3W9cmiJHYKQ#ޫ;~DԮ*(,A8x$VIj\=H\u^$nXy5n3$W\JƜfL׶<62$MwYK HuBp{"\)_TUțV,A ߊs0fCldkYCLU21R3+XgNn #ldڂkhVCt557ԕ3Z*hj) {fD{AU I@ $( -@ݶ0`9q_Qq;^n]Ț-W?V@V O;\EhVU<K6o*zd+{=Ԁ`ԊV*HNg bʬA3 ^y@*`{T3٘4!mXԿe1 T@`7cާŇ-nB͌Bhh$+3?ҘPB4n.g~y29)zi  =?.ⱺ p44IU z^W{t"qޘiL0k Mnr:PS,1+Sk y=2[ 8FmӚ A(A(9jz Oj[SV#ˀzT= DTPFT6@|⯸U&2*Zvc{F|\~hPl39=I58|3t{>ƫQ;p8j_^6pP[W[_.y80.K\1f:Ԉ <է׀֋v%>РZnV ڭ#X 9HL>ܓ>}~XW(sN&5t>jA '*U ڷCyi> AUDzPHA&e+ ^[Af1@6#T;`1Ejӻpw҂;C }:ܲ3ҫ_'uGSy縣0X99i5<Ѱ;lY'.#  3$F$ͻs&W/2a}@ERPHAZr 1 y(_3AJӝ P[襖 W'%7dj6H `O@.95dQ.\zصmM쐨D3SYj+O[@p>2֙>µ*TfG4.I W)wg&`OUk.85sc>N/6n=0TgA͠?JZ:_,։Ň?Dl݃67ūW S+c$1${ jlm9;N)7? ]]\\ŭlW+++ f2Lq厚e ACBU<+LXn8#u N=RE =4<؁uֹlAV,{|׋˷/>;(@x:{#&eI_zgk{:B!x6N"'(yϽNOz6DESތDS=hI As&s5"ziD=NW]G]t&Gtdz/*bq__O۸\nWW`BDApQxk=+#fVy1kў5=\9(N{fXͺ~HjQ7r6'i-r15cXeM M+1az D w4VV"+`#*MY[!sب`XȮU;K+n*`Or׏GxI1WϷqՋbq^:ꇍg "myԺu.\H\H?Q%e?^^Z#;I=a;GZ "9?Һ&N'ک&XO^$$Ȭ1!S@#)ݘO~xO5Q_0 \JekڮD3#Ҷ aTWm\}Jn"\+F'ڧ}C8\T@p,bt(bW5q I{+Wg] Z N?Q7PFjiecxl?ifN樰1MqKO /l* 8CPV銯`i{\6H)=)ū,Xo'`V'l6sJH8EA4f ՑCmc?lU\7Is{Zk>GJ)Z i25XZh icG⏰$?ַRᶻw(BqUu>ai]ku[Dy˕^עrV;L.=i-_+9ڝ 'UȋVl2U"5jΗzU1gMUgwf$[͙͒A Y#vͯ%JJI-;0&m"IH졆Pdt &J\h 3@ ʠSt1!YX Ҁc悵ZAܣ 떈P2[æ@7x#j9qZDV {Pv⵸;\TA=h*\ u< E^̥[jTK&+,n\Vw(R2~Rܘh:*[W-=JbM:Nާ ޳)ta1Өgbl;r uJ<4-"x9T_]AfBW1 @lFN~ӒD憟pzV&LJInLګ6`ֳ5XLnuhҲi5HL궳ޥH]L($1#f6 n!RLMbfrY[)O:3ܤ` X'O5+2wW5hgkZ"63Y[Kr7@~k >ڌ7* ebV_Ĝ( 5wPg-T}{G4n o1:xk"qv=2~+EnvޱXcuK>klK((Aj&̐bz\4zvՀ\`#51 {7PURIZWAր6iqހlˉAb3 GPGpXU 40h%vݵ#Vـ P] qcIpRz|{ 68UAV mI3,B l"%@y>=FĢQE^n-3сo`s2#s %BTb3&Md A)m37E`8f(f?p8Avť6ze-\[[F  wPU,m'YMjZt1 Dc]ypW뿒Kı`f@W.|%dPJWuoJ\Ddvܢ|TkKhI1X#zo@;P *P&-5 qnڌN]T桇 ѝdְ"?fe U'WlA$T)i#*x@Nɦn!aH K^ۿp{b,vTe>cqMkVtoԖ;d w[9D,c V-6n'dQNE\e+Zf]&9ÈB8 +^Gkga{q<ڹU Lq\lvR&{W:bJ0t("렖ojh{T( +WHtTlZ[W҈R9bu04Taf`tRv[/T) h瘯Ͼ2f f2 U{wcRZL(2 ޚN֔\J굊nLPS`xWl jvT1R}"*ԅS`eހ7s51ZPU]]ʑ$.]"\sງW!z]%r_Dk6p,BhILx<=z|`8xi7`y#oVnk+ˎ׻}ܞ=mrgPr'⦯f cQyhQfOjHaX(@snpyab",&"Lڍ`M(n3WMZ3ϱdbXak^ H#h|]d5˂uIn# y^[^絷n8F7vגQW&H~+絺KwI%kD<4m5-rqzG52,rޭ[j1'(32+(%DzV $8w^e ȫjZҺFPK$񸘃]dE[ 'm^9=D&jM\UA-L5iIUf+SۇcSUg1v*Q@5IWmHѶ:uuHkSCC݅j*ۺ= A3*Qyv[Z]IcRbO FFOTVI8 HJ;:u2rt6Ť40+P8BVϙI2}=LZ]6fG5֔EL:k[l V"*u=Yڽt1ۉ5LAEf]r FpM\HFդmH{n P$P;yz&;jEʨ4I kp3@/iMkYSe^ǽB>\4L@:V=eөER#B0mD@⡚"TiLC3<]ARjņ%uVQ@9"}#@ r_J'nHp\ `~(qy*!m R=KNjq U&Hm憫^;>d`ՋM]YUFsc46[r1ɎQ^F"Hn"xF; ⥺V8ځylcqT{` VYF@wb=)"Htf'aZ "q#V'5d34`C1>SQSԒj5Zg#Zֶ*ZbRP{h}@VUGR`TSjXhA9Js@LLZ: uA0c"zՒUNGz2xPF n\ @nPL8dIbdd]]܃@uD۷9נ}ߴ%,:r6=}UfZ0ێwY\@"N85\(+UD-%AT. ޴6nb\EQJ](t5<{VL.F3@p:w~a 65J1N!rha*J#V(z$Z,w9`B괍 dQqDbwj[ aq(jm I֨@* Q8$h|4@=yڻIHɻϣ4xD]>ǽ08 ҁp`P:l634AMK ]$H_|P {hoJ! ҵ \m M)83dR>>_Q$#?z[ɾqfd1kz8Zb$ז\ ۛ"GI5kvۀpjqgk*N>)#LfSn۵0@/S6miaL z^h%WL mi» 桫;fTV@TSnnSU.G+V[,Lӿz0u P͒[% Mh3p'P@[ 5J֞[$sTVUb]"ZQzhy= n^YI;Uk[6 v5Hf޵b _Q6B"( "g<7լ8{r$\MSZG:yX*r? EIcAV_Ydf &;Wn.u 0ay>soPsW_nݼd9u<Į-1TG)\Iזu$Nj$WMx0:sST V$X}Z3 (%u2M9eEW0?xzcӅYy=Nь H:)f+;,H2MJ%`b9oIޱB{S@ 8nI& !7}$ .փ@K@'Z%#ѕ :M{sSCdJw]zr2MpzIq};sK,)!@ _+~7Wjץ0pGjsZ%ed vçMc8'Ty԰g~k"`ߊԤ` V "VI+R >Ƃ[T;U#IH]$B6#>DT2ǽuT#cW"*͓nr&B$֫^S0Qځ.;~QP ~7SAsr'wV:E)\:y^!A6:Ż:}95FOHڹն4ɲܘ޹/sjjʰ8]@R.\9 sޥRΤ汸@ F>j[iS=mNiׯ511)Z,X =.-j$oJQW[ōjAh}I@9`[$GBg'=j˴DtEVkzIK9$WIu"8WWu$|g>svu5s$׃^ Va#V)?$?ҳ5nE$Čց fVYVOzX1F"ha9iظn0D*h.[( j WzTߏji(HM 8+p+5Ja~* 2fk*D }BoLT)51 ]zU5*Ս+R*(,3Z7 <221HDl "D٭)e*[[H ̖STi$vD$d [O~FD8=>5Guo4;uVT )[m4x+EP~Z+~"I;0(i$sֆjL׭W'X1H =PkDH}+AX 9hu;|Pv]˂:U1 hReXrhfR/FU os 'Z N q@kS9'Uߥ-T'i4/!#d}Ce# ց |I8w[p[ 'jTޒw{"7 T+ *voc@{(v2"=^ѐ?1X)Z[u `Xa!oSPo[k{[1+c 57LCr(2&W9359}y^WYE ,(J?a9V:&-/9 JȠmWAdo*GzQ?s')\Ipgጓ U%^}Dph.v a" jߘz, P8'D)Qub`phҫ787,Gh[jzsHmGC*TYe@[,kaXmP4/HוŇ^6ۉq &@5+ ;08Ա7B̃TvH[#(ںMNjhكYrfc\xː&` kQ]skcZ] =EkH#HrHocޠ-#8$w5QJx1Ukӥ\*Vx@W]grm f{cs#|I<[Ifbjl\}ae_~i6!w"zQяѬ'hĹh#T;y0$U5E<ւЫ(;FbFvo(V)cJZ*Qk?O߁TN?A1UOm&zbA AfubOLUD+y=:Ht۟#JWwn1wME.y^2@bzZ26#/>?eu/R#]mp#?ڹZyߌi| i!sL8jXF3,fMCSpW"\!uj"*"145ݞC x;Ѳ$1* 5 tǰIC84`Z2LJbcsٷR~#W|) 9'y~%#bE|[i"ݑ \jeqQxdpc Tx-̟nk1zèZv1Q;Fh#mzM43x.%&GڳͲp3޴Fӕm`f_. Lޕvb= 'lǵ# [$惚PY wb)Xovi(UE/Xt:q@B$V!䓑ҥlcAl8@#[lHQ \,z{T޶e prf1ܮ(؍یnV;5UC")"PmޫI3%1h"*G(@ۛM 5Nm@6y uF~LI]H-[vA8?д܀U/A_OR+0{T1ZQ&U?{V v3)V-v}{si\UE2HQ<p+ńɊ Lup%c V4Ga=jj%j62MeXn$Զ p TVo r]IEh)#z eR LM9Vz)evZ`UfpX)vFcY0o H0pVOR{9t_ܵ)ij^ [O(p [(Բ~H-rvڴ!Xğza<7ߡұca h ѥ|ad ~kp.l{ fGch }+;b[{PB)FTnщ z$ީ4t,$QYt" $!`qؐ#**3g[0GUA2&b;vqAVSJYɂiV B{r#hinS[kQp1 w K(7Pn1҆ jTU1+}U*fjm, ց^=H>mP#X:mCt,0H5q)fS<{WH<`Pjgt5BOA7M8aVzý8=+@_@VX&D m|U+(ܪM*kP!ejW[Nn ߴG4ZEM*ܹݎL&ctbׯ漽ǧ/L׏G#}N:W :q l]&Tz2 `-֦F;(q5:xZ'w?\IJCDL7F ?j`` {T0h!U$G+W-!p:Y˝T 39ڲ,+ij#DW"OtziK Ht&g_ 8k ci*{LOSSזX։ImY:v<ѕip2;D֘ {u(P+`U1X<oJs@ch ;t/]泒\j`Fַ׽[PmǴ/ D³xNE+s i"(7JV-=&ѮӚct;AfXS&hPAi0{Ls9CL׷0pN()QrIqJ)f\H\V-@;Lŏ3AI.s<ނIVU94vb7<j)]pgy+εcH#=svDYwDsY[M #45 i#֊2hW6`{ jRCTM+]>iJG[sӃ5"W.=;ʩY-LX}xպe+<+D/. vP^QX 4M_=RCd"(ÛBrbq/lCC#׶@"yi8'ZkH{F&Z,ںӳ|v~j*;I0`+ 歔k7CŰ'lJ"oI:}Rm.^`m3]#1mn)tGzSbɵiؕNeEONr_|2܆sW.ӎxiӖk$^;JZ@@=jvkfA #d Im}9`+AP `]$\dmU#tow;"Ī" 6TE+crlW:^Uў I\ 0F,YN3pZcl vNQFVdjvXhcoIj,bglgz`nWYpx#&,NmmAFU;IPIxF)jIW&mHuGG^Hwc ]",ʤc֥wDቁ>qκ? y`15"T;$zs^YӇ/B/J9 }=W;nl0$|W*]*@W5zޢ<*Y.F XUI PgLtcѱ"$Pn+1gb+[T$ EM[}k?G1Fi)hqet~ {WP6C4`˿Ǯ}%C_&_PVVf` y\p>'Dp?zr>,ޟצ9b@& ]c"GzwuwH?y V7Re$~ivw qTHo,|Ⱇ"fP\LqY-+(̚`lɬx'zylNOQڂngZŷ3޹ֻԵ}8yoo~h# '2}\ԀڶLW5'~d59W px>~ 59VS ,Xq%eN:DbZf :pQe#@du m#YmjCPx9[Vxx]c]8h-`Z=kV|J2=*tIZOMQ`kbkuM-}\+M& ~kӴh[ chZi?NwI[5ƻFȲvCwvET=+Ӑ$uP;z XקF cKgS[F"}YXӟz07y,9]$eQMP. n@M xRx]GlFkG^#Yz{tZoNfj!맫tf>XKڍUȚj6H뤈zYi;Y_fbsY[D1+vڶIi9ZbcH9ڿDI:I@b%b$c]bݥ԰w*X5R}2-%j&кHSͥQI@$Ae]}>Rе;b'h7\3@˥@tTOA@;w|IB_1XhSҲ5KqVnl©`k4*2[ҷYA@,- Riy yryhmd$ȞJıbvUfu w8(lym#MFN0g+~9ҥY}cqwB< =EHdm= 3L%a޳YR֔=`NV@ʥ$ $MtLxcUn}₻3ʵFk|zNqH,)8ֈmygr Fh`G FB*#k{9 ukA"GJw@Q=蚝CYu+kA5- 7*1$?#j)\1#i<X:iv4qYM^h2zA""ǚ@RmVQ+c:[j]]\kgj٤EtQ3ԓsQPWz&P''<\W{pTب ,gKRjGIr&ZLvQ+ _QȢjeȚ$ɢӳs@Kn)K{ xmTs}Bݷ((9?ޯtoYZG ncӺm.Ե {k*n@Dl,dVSPGUk0r}CRa@[ҀCњpe T@)qǿʝ@!.H=;j  EUP4OlڴԡB`E9oIh+ۺrh V!v c֋2ac#hAe'sw'J0ā~(lFVYYK 'kwśR^t&ұ֑0ۉVؾWP5( Lނ,L0 +*:k)"NqRoٟHϜ%vٝYޝ%OL1x%T94Qvr};HЬn2.$vYZսqpǪLb95/׏}Uv]kVr@X+<ϧP.Sۚ`鰪zJ!/=/︸ Q+p[kw#h)r>T"=\I140lC`t&>LC( M@&\H`-X횖<2 $9w۸ĝRj.* FQ [ygUGq  4MhiKidsUXؖ":k 1Bbq̮GPzPX?bWH7v?8ł|f~թų Gڪ1c@61,TU(gb>_s׽\ƘiZV%tZZVȬ-_X*lݕ>kE{Z]`:5<:w AT4,Ujhˤjt\,&(H 5ƯQ][G~jG]?=f@0 5᪖>k FFjM>,䟀=9]"gK,FT%2Br8\3Ӣb?j1Q~+Ճi މX}<,Lb7UnA'h1Hb_w*1lSɪ$RGXZ{ZG5~mIT35֦$≬v tު1WQqUB<)_5 m™j蚨.&q] 8W8J*:/ " oNQD1ׯ.;/ ԪUQ* {cu.&8պ\uj zc+pG5;q#yw形qq^^WXճc|1\-u X tTԨ[ L¤ާU wVln2MlMat+Es~"'8]\"f u+GjϕNi'^9jE^#Ykx2zRkAZ j0ԀsLNn&N?z=FiH9{Wih[5G+VͻeL묎vt6CWi\b=fH@:e@""h%cp5h՝" jj'l0"2֙[;pֲ9yF#qր .@[JFGZEeumzyCsԄd7^vcz+i**nb;}J]tqX6ɵ= ijiBO6aP jխ=fj`ۭelPԹ=kʸrI\6=t٧qrt5Ay # *^&w,'h V䓓KhX{ԑYN0+lf-+2[\=5\Ge24eDfIB6nI+F $(%ِ=C{j~p{ VQry꣟N{(Enq5|}1 m@P-6`w1z9yw$.N Wg$cFzgژ#Ҫ%0CL1POi- h"y>Ղ n o; $ʤL@]S4Tg4bbݳVIzK[sR oLU2#d7che <$0kd6nRz+ Ucls@e i GQl@{' vкU4bA<7Z7P:4`/h8#9=yI6C+|[Jn,]m`I5GsB#hcҊ[96kbv:tY_Rcm0f/e*dm=@Ͻ0܅>DԨT6XgN{`ҌA xH#!\:-6H6Ov85þyw 3־}}\Rw'J mfUS0;qZ 3DLسmF1lZA$Mum=z{;;Xnyx3 $@9KUw?ڂvPD9#ހ{mL?ڶ [QqJֳz"lvNI'e6Cn%nvsU]n_tf uBک gQ!75-= N|ˎM5Bl^A5}Uڋ@{ة/i|ZҶ@uyfThyuʖEszjɵ\W^Q^>ĶKq} !=J{UXr.]V0{g5QjnG15ۗ BTqWd3\Q,^ 1E~AƆp$/[$qUF$k1Ѵ tMu 88ճmhbR cVd$ ڕ(vUV@ g'c|+Qoe!U]v3&JkBT O=M,S9k^u!MGrя%[AstV8/}["O.+jZq5ߗi˱u w0\8G*&#8'ڵHw@kOMgU$Q>zyH*+Rt` (.=cڲŷ-ߥtHL$oV…qln$@T[~}MT"[߭`@r )j[ EuJY_q.6pRp蕫Wj&rk[WHx{zuZMv"+^F lz>WD39\*]I,Z V{V"OV3wHxKK3Wʹ-fnMvNH1]dr\@#s5G-¬=Zo~=#$Ht9ڱq3r9ի6[y*"j:ZncU"up_pϱn"՝6DzZ[Y}#5̈́K{:tҼh֚K'Q(ܻaց]byހ y,LJDq@ۃQ: u`s HOE;!IMMv$A+,mjAVN QDl[UD$83$)"185Qwj `ӁM ډIW~6Q|'C[ˀ߰栀\I;'QE~ր-PyGcr4<gҳDmaO5M1Bg*N[p&'4R2{(SҤI8  F+\gލ/Gb$(rhiՒ${`2LA!{pj[D ՚)<dF Ur56_$-4f_iPLvRmZK֞TlbKy2$G=e5l6yM4 6!AUDU5D AR+o@ G+K o@9 њ)d9؎Lh'Y@97ۘ3[}ij?|},BXv^tmڶ }[we"1]"0ܣN`V$BUQ}@[E2h-ʆ\w& W*Kڀ K hr4VE9l3RVjp8VLU[`WkR&(k<1blI,Crj(JȑߊyPATe4.zZ>K{ `V6q.Q$P5OJ%lQPhg8j4 3prJ@-b`  pj(@&MX o˷[/Tdd[ CFV-5^ݬf}|cҾڕR3uו,9-9*ǚYu?p(zv<76.ָpJH> hڥM BIV1:\d UFQk@kk)rqbBºzx4 rOol.SӽHX@H={R{D֥&`SyKz956)S0 QZ֑!ƬH]+vd;PhYdfO5/8=ꓢmTG(i~9Sե\+79?^ ZQSi{lM 8\g UHy' z]8mIv T\ӵU1{Cl!f">*eYMF @`>pm/> ;ZkZKNV(L5~چ lo\+<(nˬ\j.rsy{EHR⢒#Q͔6'x]ݟ d { S񴸒^'SMp>vq\tW`,&0MpGF \ hNz+kUĀ;W㟰 L|Uܝ0?7,zԩWJZ+J3ZBaPXǵnv\ldkmVqYؚv㺔p1+MQPq"z MlJx'5qCyխcdm}rݘ⓱w3 s5q674ީ.\0Q,N#3Mq}?52xy䩷$s\O{.˰-Tr"w\`7bX~!iCn>+R޳"!l 288Lvs^)(nlCEdbP`==B?X hs@FqsZ0@UWi[ͲPuQw;9w6=[ɪ >W\U9LܚQ#T 6q8ۯ?O>y*zOW5xٶJ_WxZsn[ uѶܔ?ך Vnn 2c@7@c$J6%(ѮLm@2>]IoVRF  `Vi3֤N5NJіڑ#{<_7m.nNZ0xE}!Cp9n4ŇȈlFqHWXk-i[@58W)X`]ccȮ͙q| =:Qu<( #3yd :ղ^foֻG*%Fk^DOt6"7qkP{j\H?`F4j82p(T=xMhɒ#ަJ۪3XVuh$)NӀ[ct* Vb_x'Y#bHkeCu3ۘzsګ~F:wsO]dEkvfG$7#\v ɒ"d}m $U9 FKwU5&$-AyԔo_1cO+ֶ k"VE+F}=i t;Wz.8珚lKx ,~iV .%x5!b2V@` Mf~aF{VB2Q&>AvQȪ+h$KҔp ɚe#`%csXH[zҴTR8ނ VOl++bKt4h7t Wh(cm  oDQJ$0YԛqbͲ꓌-y p:4K!tс[eɈ4: {gv%OrsY(A iF{%`b=ԃ tiZdp*Hmg3Wn2'!Vfh%w<Ȭ-uλzpI2!f&{F 2?]yz. &I]*rd5qrT1k\TF Ղ92PN҃P5HfDLY@!}0lEv@A\mAery` 4{[y [%Icw' Պ<\[aT HL7h8}Xhյ=4`TZ+5tZ!ƒL<X4i[{vu;j0+`fwzֲ gp='kޥ1ڱغ-ۅ}[ bsX}gxba?5 Ssd/Z2QoʊhV Dx[2Zz{IwMetKow@Y& sSoJn;ǧjd-z$sؖG ?9C0۟Ayci[*>ar(("QZE DuVP!Pf~q|6 ouϸޱn*KR[3=8SU-%6(]V Oa-XiB@U:$8@Z+(-Dީ(..T{ M>FHGԳc<Ѻ}M"_vnh=@ gAem33un%{f,I&~[5pPT[< `:r,TƦ\?Qtu{BI'ƍ^m 6FDwb8d SF?k;O?5Ukl#(Gʻ''2`߼ ;G^^_][zՂev(#׳|v78P"uq_Pw369Van<LH r[6 ֔d2;׏~o,ӡk{|;!j4DvUp?W!̚kǏVkYb]'(һN\fgoqҺhL ߥu^~kV޸n LXU+l[[l+fpjF IM7+LB;‚zj/ޙ_qIY}`uĎXd'Z#]3UʀX̞kR[*F>hvfkt[U4VR-}9$Py9֥4k{URŶrAAܜPHمј's|s40c͟40᎙ǖq̜NL+tIG+4M*ۆ\js8hh1RP}?4vEHQ&2Qر՘W{lI>zQH3eY-Ql`%OZ7"rf=jN[e@#Ҳ*\UpȮ5qPTiy]bWpsuAh"=ұ@}jUtZZj9XyHtVM儉z]-0O1 ]PHDɆ?֍[UaXkC(wq==6y\2Zq?OG/ K/0wa+zc,9KbvW-E5P;J#[-Q+E>sZndn#(Lp&ѿUջP];Q <(UZkds>C1(ԼX#ާmkvJ쥲Czޤgk v[8[bI2~8.:hq?|Pi e'S[TAIW{Se81VYunfٲV6fG%Ml5zP.'@UXrlj:- O_0&ԛN#,ZK n1F%,ޯRy1YWW4.\ٸA-]cm.Xrb=vk[Ћ6C+#\5Ҁ$n#V5VXd"b.T*W\i-^]J=\z#j&ƞP':&]Ow#=#]p^\mG-Z6p!fIڗAn*\>~FRJLsH\k/4ENӸGopۖo̬TGc3\ݭZ3QU:S)Lq_1{VeF( D =mHcSa2CV m X*fjJHޖ9^"GU{]t&BZHVD={UD3uCWHNpa5!F~jU.#pgx3ZBrX{QEqUdt7o$}} ѥ]^[Zva}Q5Q֯%D'kx<üD(I+WHeG:kyS6۞ǵs]Kf1UJZn<b h9s'@ڂJ uFÛʯzi\+u^;4QmHނ$sEhk2wjPG A$!zPI8cZ4:ުT;u쮭k IWkZ|"J?YkŁ 3Scص`ip+ܹKhBH{W~X:+\#.ڡlpbMͱz4B, )'V"aؒ{j̈!eLZ{TF0sZ'ښP& yYZ;^Z#L{{Q$7fx^?-zqxK#yO_;׺Uej2cy:Y{V89\6ىz9puj.̓59Sl1+j8qD im 㩠"[ju1P#\eT*R$=+93Gshe0ޘ3]c']cյUVSp*qjf?iw0F(}`zqg7dJ 3!G :(ʚs=@h8κCڸ;5VHךtxH*xk߉ٳe$+2MyoLcޜ[,u?neoՖ_v`L/HW9Em_-8Yӗ;#Q\L{?j9s+ݿ{+\ԛ:oK #߸9ZrsxT8Z#4KVr"tqt9iw@"chӅ@Aʓ9WDRvYWt62ڪAT qVY\-6 UbWlYށ BX|{Q\@}JkYAV--sB\u rh{h+߹'jhTLG'&1Y?n#ۥQ]JlX mGAfOj3 $F6$F.<@;0Dq8kNw!*Em*{G(6 ~&Cu :2/DQiv(Vc8@[pUXYDn{qޤF2T䎀P!vn:PX]h=k]9ߧބ er{Q+;怖a4:#SP[Q#Q^l'tqڱ],nS(&v RYZvAQEB}yY[norI2\nAV ?ցNVQmq@Z݋X .^, Z{^qne 1DYӾ=++t 鑚YLTHv3wt0dn' TV_Qk̶r7"P[D[ DOO+D:`Ki]r$&-3s($+eē$1':}+`Wv\j>ߨ]bErm gʺ$*Š<ՋB̄*vfQ:?U::ԑ{$QxU 2c" b7ssFi,~j0vX Cu}4n5Ĵ=륻w@UܲTkNo3b[5ۗ WXBm1+Q;Z`F%yb#ڊC`l vGkЀsPJՕU։V=8DČȂ@!}ZfG75M ml090+Vt%+p5ł6ޥ n XSVpUH۹w[#ϧgR@X [kB\1&6LI%8$UA1a bkEţ2Gh6X[#ߩlVp7'nr{LS\sО:T)YfmrmԈ]gXɎ=+޺n.,#U.^} ~.Qwukrx9\_\dqW~^W(C'\,vF!8T ֧vm w7Q ;Zhr jؾlD&7DAېH`~H4b$NI9NgVȬBf wb+q5ā([C3#+9=uW6̚ꎣLGQPi\]E5* @yi l8d\{crdPJRK:,Xf},:V+[E;5DZ7훖f]HnYm.1VzUᨾnSֵ?Bj[ pǠ52=쾢J#tZ{ʷL]=j4K <V(oTmAɬ41 G;{vgSjٺqK$s6lx7ޱ8\6$A#ڸ> </+W\a LDf_UkΒ̴F=p{f.ݽ䓶6E'Qy@9]"hh5*P醷H6c]JdcU*IVbKW[vN;b^d9bHZ+5{FcUazUk,d XNP}4bܞ'ѼΤnCl rkQ\L|ّٮ ms"\(Ϟƺ%s]"k>䚸E +k'*cu,+b H!W |U/?ʨh w5|VTtw(Q?ןnTu ]bP aJ=󮱹pz"q, $ۤsݑ|;* HУ5CGK0&rhmWՑVq}iet:gJʧ7Moc A!$ כ_Q[> "&:ExW$ Wo.d ͽl=sV:>i24Z,#ڠ"@4 & c&sY[c6M)enRbyPPmѐb}'F`A?zy.;{55l2$7xW{yda(Nӭpџlַ^YN41QT矚q>+|gw3xH".1-&:PdEh 5V% jLX$DS{ `$I zH2f$ utdBts[q ϽV2ozԈFGߚ [HQߤVfۅ1I4 0jY>[o\I4p`eL+P[D|BT!yC\]6!zָX0jywk]$\/ӥ@hhkv-w>5^U {=ڿb+O$M\$^X^._-tޫ>ƻ+"MV3BrlFfq[DSp8ǽRf%sKmOl9bk$G1ĭYPB u64F Q::a* դ+|Wf~/S"J倗% ;PD738AWSuzLLƙ1sR ¨q'FDA+l 3@+YN\7@`p} -(;`0,]vUm~' r5 jk9-.wO=$s[ *J3Z=>Ɔd (čj`N8[tch73mY% mh<Ԉ UQY6ycqQ]tuE&sPg"L~k024ۀ ֡/ `FX謽DmB >ph7Mh93Ƴ@'KbۆݶVg?H$A#.߲6ۨ5 y0;b  )d03qF䄸 I81+0SREMPp9}:Eg_6IXZ 2kXκ"7b5Ψ! $` 1- ) ۸?aR:m,42dvF$=(?{$}D}굕1p["Dbhnu}/oϸ͔`H]erK{Ih&['o mG vk}tGL *Nw2GZ(݃ё4M)]e1<5L0]8;u<zfH*J0c4{E0H>`Gڨ'$dH>Rl9yւB[gzFr3r?R\uX3ʓ1&WX^}Ĩ?$+='s\"dehLi ^ӬFGleiiϢdUg[uERJ{ ( 'A;V;`v6A ӥ5`Q$**k65Q_NX5Op %.Zsi21MgQ%7GoTmB] Lڵ yX j`nYE v{5պ|D l9msSxmErļOt \v8jc5Ԁ\Ը#*/[g: UGc^ߏ5VE1'⾟ԯlWN\P-\ #%{a@Ǿ* >;[#Humiyzn};vu6)0XvaT?K4XkN5z?F&L5֢p9B2GJE[`KWT-;$H{ַ PZ6ҳ_x~=+:Õ +)9ԩP6<H ljQ[+ISҨbkY;Ozn+u/y`j'UmuL05Is)h$#U!km} Tb@9>FnɎDU`HȦGX{k'Գ;nX-,A"LW^@}@r7T(+5:LXhK> uU:lf$$^kK8 ;Ⲏ#Ua Q봤1ӧU6cSV̿iA41ҋ 9&[>`a|~hy&bh&z!aLQXQIcYHPmO+>ƁQhI&bXaI9I]_@t,ϥۗ#5|]o/s+j퍥 ɓum:ңĹ+Ijs('hqU/ɹ\#9X*b&cD(F(g&::{g4 V[.x v0"f*[c)2'iēKRq|HTب.oԄwqޣO׵ e,\?P_WAY'|&鸁S ۶`Pc$/%k WXCTXkr3|5F:zְB9se\ J'j5`N8(nȘ(H$"[HRDZ47DuZhBYE{azOG[`AԆڳbLW:Kq1YV2Z8FH#_"G ZB*sYwԖPLMo5~zzLn-ԑLfJfpnSiL*=~+S1ոgƑ(gDɫz֝ञ1uK b20gx"èx"9Uh*ֺDu$z/ jHZ\,>=#5zVY+T-%OIMw, u}Z* RAn6e u׊kay&ý`v ⍀\P@#?cFկ!k{|;A VU{EZR`kי@Oz6DjLLZ䜎gfee*2zF7Lc"s[A_p 8k1'2>+t H$ $1J/`F[!Ю&~joVNb[z+{VbeYY* z47G5 !7 Ā喀;Vٕ&\$@ѩGZޞotZ3H2X[XoڤHlU7c ۡ9CP Q|OJ.nI'cu[Ud'ܑ1(̟CVQ`J '?['yrk%hkw F`:'4ԓ8=s{Xz+{D´ާ[^ ;7ȑzqE|?'H OZRMɃE흳 5nP+eѶkEA@A3FU1=E]( ssnjGKaG<=N ڽDb"% ˶vށr~{sF` _oz4<4J=0AP.p8T]R 0Oz+Lށq1A;X^Gz^kp98=%I2;P1BbvK*Ij3Eb_.{],YOJXVq8Eݱ2+`-\k@a QVI }H/>3\r78# ; *癭3iKn={Qj jY="QTLKf }Q'tWh?k_OH-Ƌ+G 31QAu^N: ^/91'$h ~, cEMu}Orţ y\`wz]x_nz]ds:쁃\k}N,yUE+.mߞՍVU%ԭkItH|cTjiXoFVPA1'<BBzW֦m-4I4b*-·$EI0+4:c| u`[2EeD*C32:ε;7ZYI ]aQ&ܐs ܽkT<0T"I!H{͔cެE!>'JՄ +G 'hl=A9*c|uյoQ\7֗ql;!xOv\ "LD"֙ sA iڸnhS׭k-cU]?hDAmn"zoWdO^lEqu! yW˧mS… n4;QW-ngj,jH N=5fͶv ĩYl7p`-:sa>[}Z@6̌汲!۸J;6Ց$=hY$52mڿxJA4XD(ʊdWS¯l=95_Ox_Sd>?O'= j+`v.Ҳ0aIϷjk\oo,x*+T'kAzƙ3zN(P'ۥ@*`jsSD0` w,#FX1][kCPV3S{(Bڲ[^-}nw`Ԟ˻kgMwUo&8* :~+ߢ6OC>m{q3m"DVWqe{T+bg3]"k~N?~cy߈jϚtLrKĵ0 PD'5B@@ĚDHY>G;[:[gi=sVш1W"*iBMZXEHݵ fXDT$?L9UC,;N~k`R6A W<&WU ௨qDƟ U.$D}2$U$+:eu,~Ǜr ":5 O#ǓAVcGkGjk33DJřMR*\^F0Oͷf n \ h!NzѰE\{Rݷ(B, oz;V m(*(7֎d`qJqT46 j5b:{ & 3ְB5`=b^!HPQUHkz &I6}HX=3F"3IEShtedB,G1fKks {z` Fp+5VpfGzi\Ak jHPQ lk/*yvf=eފٽpRa;29f4`n7V?q+&35drŽ[͹t^vMtV8,u Ȭ{ukŔo<AyYy6S 2:V RIđڴX+o*: C{v4M:4U#Mzw LjJļ?I+$s\Ttr0kKWXcPuUQXbB?th"dֱ]]QUii~U,RuZܑ1lEv40 t>a[˻Ѱ[!AoQhmNID/HP^E75ՠT?~tK #k>p?:iVp@a5Q5iWeH0|(ca}!,=o)㷷z QknXh੕j怀Ƞر0xb;)M{{@ګD jK!`Hx⁄^2#JU'l'S[&q't+CHǵRhdX"GZFPʘz1{P%p5푎b T4DA ]nI4le߾V&d^&pӯ+W 0 F Eej,,5Z{2ޓ PEnF>m- lʠĕJ?w sGT- p` }W*W㚝YXu[-nʮ3uɹ Tk5mb n*-J Bv{T$ܼgR m~-17RI=zX7@Mm*C[ܞkbVж P6[jJwZ]J=:SCin2Bݝ'Ȭ%ncujOl[A3cW+ hE X$IBr˛>+EHop;g$oW^z% k&1d*0A< ʙ>E n@^9.12;dk,@gm#9|'"CDa?ڢ񟆳qtW+۪Өw0+{?U XݷuT0OcTYC>@uK) mfSt$ m {`^CN9zc ƮW;hͷ!z+ ]7 `b*B?LfkLX#\ζ%#~¶%r1\HGRFTMn(~aDeuհ{C'K5O9݁q]Ywv t' Vhvܘ5M߶'9[yxn9/zbr/@=wFVDV]qW7x.EX4]sHʬ0=%2@ÏcoH2c\"!*=~V]g5^~ϼd_pGx=u[3Rǎ]imۅ8#>r+MAL˥kYEܻ mb My[KQ+uַ5XIP*Tz9NP1S`> g`Q($@9A]'u$t1;PhIܜVVa`tњC[FzyN?Ÿ Ń88?"dm |5CJLn"YmV,@gڷ5p\",!EUQ]#kزʋ0tk q+@/$'Q t jnYk"bƓJ,Jr{U12_ZuOڶ pO~HHXF7 @|Dn5 Oih@M\H5&RfST$y@l3$GNzWFb?\VAXf_bI8^qqҊZgon~)Z x0>*zDG I(F;Dd(a- YHY`(35iOq.r,H8FQmcxIxqZӆVPy4dU^4QUb(;36cA w4UKz{{ֆ d'c0#x^@֘0'F~"6OIAh4a jjm ?zu٤ cIbkp"A2b;5)? :39lD 1F<vTD/`҂FH*@#3mQD2 ĉݜ}PvA@1A"B= i6ԹO[#uM] FIkRϦe\4 E=-iGs"@ SVW%f@(PMq`j;q@sGz.W sT7AXJChA r(pn>)~jWG`~8=ctiֆqT8c/ib)0":M8K9[XR Afky(&HNjIm&g"̡#0WWr"~h%n˹v|c3@ $ĞHjTz5Kl@dfjs1fFu˛-hpk5z8B?jƧzZ*=z YYKQhB_Ui*P7[6䎴*Qv9V5<~Dڨ|QeĀ:+_;Đ k<T*Dk9@&@9P} Vǃzb-zRv<:h.uj-3x9$Dѕs$VOz$"Gn5*z橄-#+9h &+w~iJVɷ\nͳ 1&QV~Ae݂&#eEQx0gEsV,d#QJ/tB)(DOYJ ;E:PoLUwnѸVpgU d Wպ7@kRVݐD 2P'vaZinBg dh+wKPkzBE%f|U1fƽ :[.mC7nc6jTG8 uV_-D{~QZOY8U/kMrj'2Ϧ lBQ'+B]=D8Kw6$c?z%"ݹTP,zA+bt5.H| S+EOt8vkG$ҹI@]esW$H1SRK3RhQmm5U% ӺY=SהY&EZP%p9Rp;:U?GTNfV au\71D d?WErTDt BR@M啭X֮9X;׫t.NHp-\c*W[:--ۅg]s-n9$SʺHq+qkIuQf c廙V=IUQh{u.9#"s?޼0K@FmZ3($ԍ'SC2 P5T9',mHF |&p0ph&@9v=eB0ת .[y+/RD-q}$q>ҾȻ_K'eҦ&9?x&1ɪTɋ?px[|>本W\zK]G5o3.@*۴w+Aչ CpD'ԴGIiٶ]!Aֲš`R$4vA_SiA$]"1;p(GjA`;˝cr}xdCqG:]`=\aZ%P(T@*%('QKHcyk3Ex]㗀ݺ"FAOF'8(!v8YDVg0:T]ܭhA.LRl)Q,ɩj7PF $Ln7B("JAYTLi(& " ?HA=9B FzV+m2o\]#jM+5+*Em9:XL՗MTVex]R{㿷n[eP lzIAS{DsQ5nՙ\WA@45:O7$Fd⍃h $b\dKYv@1?4ojv\ 5:f${+p8n0``dcsO0*J$|ЁIw;z1`K3w0eQo2R?LhH zeKY<{QeiՔ(>hۋl=LOɠJMf]B1$k4g,A@ml)9@Ȭ9ڷA/ie)iPē>ɦk6 p~+P"O_Ư+mH0GI@춡AϱJoQ^R bp>hٸn(Ԣ(['-Z.WAiX oi 2 Ze^ܫN 4M’BA6v/HҦ9޽+n K@ڹ]#>1R #==yG.U}^x!bg'=;T( 1"H[>`4X+ȏbӓWI4z}N &0En=hɒ:sZiB?ެapLm"gRE6tB `(-y-[ m$SA8dWPC/zR), G}R kk*W* m!\V~*q/9 `=R2vUa/1 հQkuRzV!+VnAjV[d4&aWnq7S[n#9#'XTIOQ;_ҁa  $֭{O}=%Y m1#&˖B- >\UہM\\O<]c7O< \nʿi9{W~b[A#?z s3oux-w|4ն%q\*-+TGIrn_D~4mK[kd9ϵ&JcY\lp~/ Jc %s޻XZ3vBEҧҮ"_]"H1ق'F7[hyf0u lm8T+UGTDRk>d$NnlXe 9nե2s]""|۷?ZZ95QyTjیSh |BVfN-qW#UYtUIڽ{Gk1N1oNڶ%z ]+Ȣ59OŤd@rGz"@k5݊#Q maø?s]"\WJݴS5jҍA#jSA0: E1n& L )'+q5LMobĂ$4HZmWȟoqU*qkZ`$M|A'"TɪWy騱'nF\v;@K"|HګfocRnxҀwK[q1V`<jViYVI4-؜bó;MK'[!+p?l mL Z n,&Y`q=nۼc#54Qy0!xy*"︋Nx?3P A?407XGHwW6Ďhn硐:ȫ 3 ܣfOCMe.meQ3=歫CLNZ -NtTā a*w?Y ڽ5$}% M>>E`3[ VXEE{;= ՝'=9 GJhsת7Hp),#qT \rbB3nձԀOD&/O5dGkݠc"6_Q,-!;T,@ >(33wZ&z44RPzvQř*3( CQs (2 :=@80/-nֆwD =A@ԣ6 myW@vtZqNMrPw\zuw\\`zW{cnxt` 6 [jCMdHy~?D=5ѻAd@@@k).eD*2k(*0 +&$|sT%n&Gތ ``sֶ2?D&z藶 =*Z $ytƕ@}x,qGms,X)  @- FD%Dg{dZVm4@&k`ށ<T#q%nCbpzUāPE4O/ GRO$%i"25 Vcr kyl$2#Xd@G4MKd@];L>EnX`NOAZd=LEhHȇw:Ѹ.>(b7$R(Mw%\M8$ &"m^UvяҀYXA$w9-zqv<1\in9q8423 bb}&Vr ޶[Xy \'xaP5W{(n;s)V)%7(^j+~D,O皚]T*%-*PSkg5jWT3mՂF wp?4vdoA,"U;$zZʷcRm&XŤo';k*PvNjVm]ʎXyHoWMH˫/^@^0=j~?Xт?yw =#"qPS]AR?͖ssxN(x廂ӂUf}ȩc5=GK0kDچ,-t[DMӑ$NwQh9UqGuWr(+W0{U2iѷ)P `L[` ~3RoGX r cP:-u) 7E1MlGu/`z p91 d iQb,o\ڣv棨f-;0'3z]FXayskBXO~jQڵiO^^_ZN+ŴMxiV1#k8wl 21.[]g.+m XáܵW 7xvIQ ׮W_±bWi\+ث\W:{xU{SmIjV>Ֆ!H1VSU -}Sl~jCWlJn78:(pe*Y7ٷ@nlX7H_n5nucsu% v^IV3V鎢 R?jhiKۖw7_oa]#^e-z#WD @O"4[ZQxz{,݀;UsE6+]yEn~ZR j~kl[֏ - Is'}9uU1"ktgP/N:&!t1\Oڊ"93mS Q[+e4)I?`0"&i-hf1)YޥW&M!~"2hYHBI"3Af?z4 @y=굕&c?]WށkH8z`W㮀p*){eI5Ύ[R-9K'۠5»&4rGJW.~*]%[T5-D,` }Crܴi:uiZgSPI tt༱TԂHtsSJB&",3B0p ~ ]m.L4d)t߽ \lGXylOEn&c=**[P9v0EqY#z渃 1qUɹq?}+r Kt#cPЦ HҠpG'Q.L+PjY`awڀvJ mH=k(88 mMp:C*$ tj.Z`}5EꕴݳK}GO W<}&лHo[eZWx;n`?ڍ{0H,;HsFf{[p#Vě7IZfO `dVqY' FZħzㅛcssE@Uǚ2k,'hvVZ2^ӝb `9]C.` Ii?A*$4l%7ҨM,H@-A&W@`Bw+@Oѝ3M;~yw5 JI*m2sPW $5k} `E:vd&s|$v5<&uWFXB~ǐzV3-u䏚k\)ݘnhp>W'.A8F&I?z20YQ"|ܦAXUSnTQtfX'T-PT 6F;:-bɘ$@[(7z Rs$[2:rkQ`"d{tԮ̾c7>di5E.޹BD'pk[ݳ`CzMMR6c8Ͼ55l۷oIїո1pg'mdӊŋΥӭHK6 $ԤCW?:Y5a2cZhcDbʣ%nг唜OjĦ{mz1l?4h\hw4RWC`?N(ÓDѻm,GE%éNL2'?SwZI; h3q\j}!e舍M:H-1sVGUv{bЁ"L((@e"}y<=!ZPrv/* nC߭s8 ҂ޒc'+-W]sںys^3VRz7QIW?o-C_0MuutXT5`myWX(,RD1Qڵ5mwzU"v1xeafksHzʿwnEt΃CVȿi^<1ҺG:;|UF1V++E<ͣ=+ +qsk@9HT""@MlF2^"6& xV$;ӔWoTR>+uj k8oDuT@fn{\4۹1QWqR q榩@n֨h,I@#5mH?-bj&2ނ I4 "2Ii Q[8'.BN'z|UǷ-Ü z]\c;Du5c}q]uS]691#k_w=jX*@d59Z{Pg~h] Ek)5a7@[Uq98_ ]s> 9#3ڽU䃁޻S'&i s$>*V01F 5lY2 4V73CLTQĉh̓+'\o0Znlуށ V6YV bAUQ1k,ld;V(2>{ %OzųEON}Č3A(g8v$k'X ( hζ:`El,Dq֗Hs[*P9?nձ`yIEtȗ%A҂ =FF{Zt₅/dʊEqkRIz5=NjD4 wOaE@8l_0'F+=,$Ykd_$9,4ZbGYUƇxpH N =v6ŴĖW:sz29+Eq«S@bYLӨ+$qE׶+#Lj& |Mn.qM0G֫]j㸭œZ`o1vFޔ=>嫲 R, E[+mMOj 11ӜEmVD;J-i*,0GZ\9nRfajSmBW\H Ēxpu+&ъn ܑ0Oi|0Ehb;LvunS+#Hϻgk$SF}{GgSUv^`\M'hii:ߊ ދ0#mMw1T+3VAd hևz\piE[L':V+R*$ܶx'"($ynjtDy5&-$WVЬH Sӣgh F:k fN}[w4`S=P( ҉^aRH'+*opx$GaR%tm ` J10;z,܌@ ֡wFz F :SpA'h(؅rdk)C{+eڢ1im( Q[Z4~fUu+h:*jUgit. "2 zX$R؀=;TV5ۓTK-@T2!ÛG9@֭ӈP+aWPImb:tXcDZ}%4YH&s'?޽3 913ק+rS4Kfj. @+m>?z o% @&#$ J:m l0(Ll%ؠWnڀ41( -VeX Z!(d-h$X0OI-ФFQrA$L9bzV ѿXrxU}G1QTBMp-Lp[ɩE YtVrO9X$MTy$4gj5`r~‚@1'ڍ Uvɣ{%gF #ۚ4]E2X5*nmgFnd%ہX'66VAdl2y y#MK/%N#{z[x/Fs=x{o([݁XIkζ b{@)"$.Р/1KR5z-I'=+^v$A^(+ӓEBKm`CGJ XgtS#4k$2 u_ FIU1j4јr!ds'бbޤghO,D$gCVK[k̹lZ-=?52uZ%q'jjĖG^jV $] 9fzզmjn7_TeKNFJէlMd~O_nbޒ6r"4kOj6Įm މmyEjo]LϤr G6/^KlM@{-[M@;Fgzԭzy.H`xẂ5j=nŊ>YSc@_EEG5]p4tm.7Gj޴ͪi0;\cVٓjNLSji 6v.VAfALg?ڼFm. =qmV+_a\Sg|W]j9.GjyWt'j^>]!k5j8+dVsWYz8U3iTu6#vK+ 3zե,>1VVZzDϹ =r5rvuNqFb9>0OWXm=?vUq8ܚ#Z[=r?eAyLnk *.OaV;ܙPhln$'W['iň q]ctnlm"bT]AaZ/| 7eS'tv@+c:ⅷ=JHR>IF[-0P"vɉ4WݖU?՞Ony2z8  BA-AS?ed 3Y+jV :9&y:gH=(z D9M::K\Gޢ:ۗ {jcv5»Jԛn;l޸]W6ZR6AN*$61ɬWV7ZzZ&X=+p#$&"-a(%41;J;jW qSU#m@=i<]} }.Ӫٴ [ Z}ё^kmfG;ty S>ֿ;vG*LJ]sojzsӕyzgz#r>$@ҹU{-$UL: @RBLɊʮ,ɜֱ]*DEzQuxT: rY+ ]rZbAz$Wxְvq&j>lsD,+GIQ;vvl w)eN".Emю(14m,c@inOj\;PKr$ϷJ"0Dz}\H==VmBOYYڀ %HjkbJ}FkLAT)YfKTĠS$JЃfQFRmXel0hFK|$O_Dc-2GqM5O1ܓDO;MN 4] q=MR[#FjS"&z{QڅrR663mwq[Qx ($c5bH M<{BF?j N:k|] daq+g_D7z >:~"` NCq-FL}l le1\SE~FkirGɡL׀}L!36{sE`P +zZjv2Ƕ*Nqe ¶ĉҤ rWނ~X0jun9 $vGUn0sq5ciKLJe$"EMr {DyŜ}T3@m nh]m3˂5"0"1$#gPy%Rr8(dV4QIv1vΤ\ ^D. im!C%52 sT,Y-b.zWzϭHl$0ӭf)of s55r֏ڹՂFjh[@Xl.4t_<=;Zѣ[@UV2A u5l&S${cWO|I^[\HR2cޯR}a=1N+q@ VN`!PJNVԬ@&rZ?z´|n=W}CQћW7m GڌZy4TIB<׷8y#^ޮZ!N$ihnma5eF6]qIJݸ=@"IU6U/mT!a^iD>sNYpI{ִm3\](eFǕLJ KNE[X [cjJ\ae,`Dz9v(_x֪[Oi*ϵj[[yL* Q'ڪ [ cyA&{)ȠmmX[ 꼅 I[.W2v7Nւvr4gwMγ0h$/@[ H* >j ?@K(vk`tӮ&h Rg/[f1Z3 ͱ<MiސL Q(ܹ[4 l#$hΣ|A;H'ߊyi, Ê QݚA?z6 a\fbnjUԫE,@ʜ搄mb[rˣ\0;#F,29mf-A*6/T;m0~6<'|w3nzDFy_;8^륏=u=嶒HSZ*K=i^~*}F+wK9OM8_0nLw=h/^sA cF9&944Ub.z2OxM礒jf%a&'5j&{U "Ę [d7Js˷Cg5RlbRdv)-*?-&E{iGKBoSɟERȼARwHގѺXj6k(en~g8E{Y ӵuԴ;YnغaDĮZ.BBĂ;vEnBH<јw.\dsYi=u[BߵbqAMcJƉ]s:oQ)EPwzu_fގ,1վ&g[SL0yFqW*jƸaWi ^:tɾQ0[Wvym۷+sej qs]cLQ(Ik5ܢ*Vm{zMsXCq1pBϰoi4?9[KuQ۴s]"*[αp2>isHE;|˖aPTu$Z%^_ RTQ4l  |T'f#Xzl(ނ sA%`fA0K:ա'@=*p;.P:t(g5"FւTHHtrLQ{FXmmfՑq^n>#wP޳<ȯ\5֤l<=4,)-'Je,3K1[ƺk:eLs\T6Ct4DG]ߚ, 3[lB?afF#{VQcIm zWtV sӇ;@6rd笞دӆB_'xyR2jrPR }[|L&Fn6T4#ǏGYv&9c[zžU'=kGPH:H]ͧBlv $ڐ3KĜV,XEцF.)~"?mUTnڧ#e`*q@gk3U@}6ɍéi ETQVݭs`%YF:cOLz erh zJFLj2(TwUFVcT1 6ı=cel1]O7 bd(`-3҆%j'(b酋CfM L]ēFU}0?Mi"#0l+mBc);#zl\?CpO"frdc41^rz4Kw9Ekt^ 0}SΥKh (LDڅ؂> kEAwky8h+ e w=;հZc qA^vF+n.&; k.nXyTXn%cΪ́h+߼[{NHڳEgʭLi;\\\k $7ugPZzzT ~HhTYT9VsTixr Dc`Ğ0=p;щؖ.h%NP>h#\@K̂J ܾVP"YZ YnKLTS~R|`$e?SrW8BnoWUхc*Lj%_VԜS:G-#ɳq٪P'F273 o!g#S,zVh}beDPA-97srBlOL+Z2Nb+wC3`аhcP+n&`vf Sy`),:V"d5hm@,c?z ,7=(J̏n"=g4f2^3FtʀZnLߵf+'&A (STsP mm^sA7r$Gj |@>ӹ'"]T_J^5 5h6W&+YjZi6 ҌQb9o>]5}s\_}MnI+'_%\UL9=IdȎ{SC[-%`bIn! vs?hbu['-S=Hvo,tTP@S IyiS%$Q65llj z%;qQި9n`ZPkAU=+j`pKc+ZN,z⦮VU[5JŲGJTԣ;I,&L4mW07eg9'ު&tzܤd~1{Lea> ;Lm5A/WyI`˵Ng>%ݗ3!b$F>(ZWB1V$+Au5˅dSwn#k~n#HMECUvV^NO=c.xeO&:TKMyH 7[_,I{VΎޱoq@js^Nf$m:uʟ@r}ؽkĖߠ\f~jzo , OJgkةobk[Y}pdNfP;QGFx&`HO{_7^w@,Gè"zY%sUjqA5ck4d<}c1k<" 'Hr^)KhnXMMZ"1]cv皗K\}ik'YtWXTق{]c;RmN+rVgv*gTqnGR* A]$B"f.: rTzIklu!cØ5 XKcN 4]Qb9"cꙎG\֥ͻqK&Th]Ê^+h@TcuYkm"gbOt'3SZfk 6o7O4Lx|(o.9frW#YCJ aDKR$v5"|?T|L]q;'\^+wZ;[z,:jmgz55\jNާ1r>Y:Q7LFW@Ie:$#G1׽1-Y-`4`L eTOqBWuέݼ.ZҺ,+1$NXgF+^F t{lo5 Ey81.`TGWtr Cdlr;4t!Vƙ՛I幀"j{LA%%F K`;Ns҈.%Q#͖$~խ]_,k5p3ǵ-V"¸Qnt3T>\*j-Q=4+tO~%qS@9= lԐa Z(w`ڽ;(K#AZcxh+A' 挪 KI֌26[pD o QsA2T<؆@ABW7$z@1WyKu4 Q?$OKN`41PzE"WPfJwfjNOzʵK(*6}H+^rI>\m\"bjmtQB⡠K"hد"f$.Z++RX4|8\Q⩚|8"Gj&ŖڲH`{M H8czrhRKbڂzu4Blj|AÉsYA? g[J&K[QnԬJˍzIz#ULDUqE>8B.w 2(v=4b Ā `zFh w34acjI>3?4 W@*@dM;,bdV,h+ ݋,sAbӱf [ N7wZ,^b+$A%soqPg_9ycxvG^?HmeƂn'T •x q$n5 bx’8@ \M[|u$GނVd["5P vvQ+eW#b[zSKV`@ȭ,P][ߵ{AUR}~')8¼N||{n<t5G*0:; a`TZ5 F]PB$?ڿu&>3\I8?伺=/ T:j:fxd׫wo Ezp^705W,q!dq!$VhD4l'pjN3IRwFvq3VuюZQFfʕsRz%^ۀR 4ň c_rJp+35SMsPn#Z,@a*kJq@цk1ZZcQ`.UV b[P958Tca%2ƎS;WIQcKGmpTa"1n =n^@&eӅo#5(N+*7 }JԺ69ƽ0+v.. y?:EXd6O8MѹW=: 2ZHfjl ")SPi:Pǹh#jo:];jkoE{wϽTi.D~rp @sʎʐy(Q=aiVU Ψl*:}V* ~ߵvn`Q &:ƊwbQTX B AoVE45d}VZ-ۺ4wz#Ф rz4 דJSGZ%\d\uRck }4DhԂzPR}j2sF,=CISASm{P$O|FUa;8m(Q#jQ 1Wym,d~h,c߭JI1SZҭ%/XO%yaB q5"sSj_Wu_2+\w1ڣ-85ƺё";7fH\ -jCEFǃNNku.Il2[ł#@_ $(-VZ+JmY;!yMVTw$fnBGMZH[H=z7<5ۗ1c(A>kz*ڪTTcҫX0;c4M bGbn>GFqߚ/$;A;ׇ[e!4 v6޴^9_0H3M{Օes("wHn[D`9 POI&ѕqm(CnGaXAލjWZ*+_J<2̟ڌUrF㪍1PSmjZz_@ q@׬6@?ڀH@ՙ~(&X*C&ӭ1Ҁkml(DGJ-鷝ksz h}ʬ{uz5a$ h+ @7]m?沎=b"M˛dJr.<7bCCm0Aڼ={85Kjn33]۴L:(M >.[ķ\։VFV>g=_m}0'4`. \q@BWɀIJX=c@Gǚ yJYAHE&J@ 0PL]{͵T)\kcIEW?cUZIi暜UsMM̼!0r)>dM5,J]!Xn7b+*ֹn '04pqHWpX11cDhfIp*hteM[0}-ĻAI Ym=ZPI''O,eM}  zƧ]aM-QDȊ67C-FӤ?Tzu:6W?T5۬n#` =t5\UR][IO*AY"!CLbAQl8 TzUcUpeB:->m#^k˄kd#Dk˿wy Z D(ku}BoH\ή Z(fy օ#ԣgUA.1&62͍٢uwD=zFt/~Uc" ?_?x(w׋ϫk6kƪl\&;9Ե!w|rģ+yzp^3RwUΌ#?vʹ}U V^I?ڶ0zhbk4k(X `SPc[`bʛi$"H?`ۊǞ108ඁǨZ 'Ơ ى'u1[⹮)\OJlcq =IC޲ ZpAڤ@9>z8{V3{GziMs;ƩY6 ì|W~v*b ?~[_}>SJE{':Ka[9SC-絺VVȐk)S*Lk˕yl͕ ק c ;vO5¹+9D5BMYo`g[種*ڛ@AGq MqKW~\Pbk.T&- =ߗ`Cf{]ilI-'ҭ6t[1ީn}"L{Mn~c₅/n*;FIBXA :*Ot5+orZ='!۽Q&C 'v0m$h 1?4N%elAV5+wXLõ0~hdZ6DH2Dvzkm"*C._sHz#uY;Ͻt5h&g0*ܪq "+$$Td;]m=>>k.0hfXRYb5p1T*2ƥqU5/5E_wڍ?T&=RQf&5~]2?^:pmWƶ[[NLtNj^F{xUq*QI($tfj,;GꞳK/xF:J n^;$Vim.%h?r'(ļAbniSu?4Td0.I ڹFxz:+Eu@[kō+-ƖWI,kؾԒcDWi\sLȮ\ʈ,O"TQ6:r~Ib^;%ȁsACj5O(AHefVF Iј9Lphm:&P[_,# wm¤S(*OkrDQ NIij,J=Oj `!t0f;61[9T ʧBf23L hch8)p l@Iyu{~pjMhOQLe7[#@-n2٬΄R$X{qMz[;QZm?( r咅Hu?WVȒvZ\`u(k& Pܴ'5Z2(hj4@^HJ֛Olx]繁R6ojDxھ:V-lK+A=*5l,$,ٺI<R ^c~Kڋ<$nT`cW3ԗ,?zW;"Z95 fy[q/zզ ~,LfA UWhbX{;݋`Mk1/(3Fa0ڍFiJ' 5mc'oOjS >nomY\kq*:͍ī%ĺQA@tYXbPF sZɸl'>mή8-%ٍEt(jYN>LzWxeTaPI_3k7?o11|ϧW@xf8{F''W{4l }jB&"Rɀfח:OK@æn ?8t.]ERtqvdaU"hDY-zH00W/uT*e ONen c"|j1'=~V:+l.sW*TFȺL{?zCĴdE1Z09V;Ozr+'kAZjZ@@I|['4*"2bM?HN P`4.1"$A"Ņ1̏z4|>0g]u<ӑ$+zާ{Imi7< STuv\NcΪ}35ZI }tfr*jp ȓE*PA} 8HSB"Ih swCYqC  -z[<˅: 'O}E΍mWnc^+FޢG3d WqTes>(|mk.u]"?]㕯5MK\P2&0>kqxf|ǟ=M7^wX؎ֺG:_bI yv&Uu`f+d~"k5PXg6}1ʮݐ{~u[ꚸӲ@HƮ9֕mua@jElbf8@M6%d"f*VBV\6&"jT1eަY;V63=S`L/@2M>av*}3'ڍ:;Q@b~Sc z)@2P-/ j6#vhPÜQ\ rI--ںG:w!H?][Y#]#XuDO5'vosA1沌ޔwxn]? i=KцU3ES;P6nwXvkDLj˸W̒$իL\=@ .Y(ݰLyFH1DRnAV+8ѱ6@zqcvjf.#l>-h( gKgRX)t{J蘲P{tv+U`}cPRsjջ cBg&,0Ĉ9Nd̃ҕLelzAS[/Ϊ'fpՂvuyj y?EuίawGz*,_p1UA-A*z{H657 *+R*3ڷ) mPqj7lPqV:Jɿ` TXU]'T Hcku=1@ ?߱@w /pqނ7!:ŕͪ TW.( !A4FݠJvԱ@LkZު929Z=e֎; yep3VSbéke=ɩ0.Cj[0TPxFHCd+q\j[ },zۥmw<OZ Z2XZ2"9.n:ҴסN $qVZT3I",K[g.ӷ3FXX{qFYTĖ?i>̊^Pv(ۃTZRk﹈1Ϋ r'ڼV,Ak!%$z8Cni.\rjLA`KHLHR1c5 :Ihցvaif!B{QB GnBbXMj}'oǵ[rzb-dך/أA[)sirT‚N.i^ǥMTGlJ ׭-F}cq?jU{Kin<eV|c\[ŮYn1=Ȯ=UǕ}Gľ|ܫ?u7k\1?tFyO5yMMtQRԠA fj\ȒYRKg8 hOj`0㱭*92]es1u{TIA'‘ zP%v 0d+@rʟ_CQ={(TėLb}CFZ!X£gKq*E1)T'<ajʱfٹj$ԩElď5 D+oYkjSyp<kj{XAS׭%NNojeAz/W6buޠ Ș 7z~Muj #y9|GӀ`_Gey~IjTC|ߓ,z|}c,oB릎8!C4@}?z׍j0hغ~0p VMNye֌VƞN3YXIޢ:s)eDoETfts'[OK f}Ek[iXRBjWOjŵB@R89?:xm*C.zKʤn?VRԔbb\UٸrN&9a?ß[c/>=͋㬯?&Eo lW{i2r95~qffgs^~k)5¸o xuxmHud%]`s' ^{NA¼`\k+%ԟ3½xOqW92* "I+J O] 5Q;wt5`I s{q3ʫ򁟵zyr*!G1l!Gs޺&-!A[H0G V+,o]%g\m Fk=b>ՕEۊTb1ЏS[9?A91ދ[s 1("A#D IN"7Hh JP]7.׽ݖ\~h|Ps@ozTyzk)A`fS+KG\k}= k.UhNF?ǵv5b6ɂ[tTz(]^JԊT5}As#MTT܅izZ" qQgǵb,wC`yYD9!$[+=MN^ 9kp IQJXҙfI'JL]$8YjH?n{ V;^[n8Ѫc.퍆y*qsL{ԩ\[bx`l؈bՆK,[' o-]qA< ?e+#pjU*PR.yNVXӱiHW+].nf`ӭv5oT#~ u ^W+G5zrvm t&^ 1;;֋FčJEs?.%OcrՆst+L$FcoGj[Cl:qV~(Uo͎SUW6УkUG .l޻sqx̱6HڍMZfo\kظH |Do񌞒kiؔ@T 8+`+N+ lj2.A'ި-2x>f-]!:äm$ $S# ;a@kk*t@mT ( !j.yt6ϗ>[ ~ť1-ųA܏w/. gr~;VbR}ucTHu'PM]PouwcjϤų}f 3z'~#Ѱ]_w #1{VbƾL##R!:#KAPwD P@-*ܸ֞@ g"ZiFk1^vZaId?1_7~^?Ï>sL ck|IG.]\_ZEzkgcL-8޺s}^LxQ29 D`v":ח| }a{vNG_ڹ;W[?HiBйC0$zSVK]ra`ߓ[ל&-IUp^%4Z7NN>=:.T"ub>b3[6 }Ӵ 1-;$"3w|c}Mz_;@ZM2 x̎luodڍ0g_w:U:RڕaPH~k|}/Oo4Lr+?P'l]Y kpk̟i\gݺ+p^9 ]"k?5W6yYŽ&5zlsڬ`xuu_Uh3Afh<>]-%@P%3WN=8 1+^ 8 6#ߘVM|dʣsVoyj7HYک -k=p8@B$gh#`[lA[`H ܮtK3g9G:ҾT ;y_0]`LF7KR19$Vjm7kFt^$pEk =CqTU|Ve`;T$S``WPHv9F Yca ֲ݁$Y+kM`x ~hq<ޕ*Wg''WӠ<]+7ōiYVۺ$?ҡژF!K޹ճT-gJ[]ÎsAYj"c%;Է`$\2DT%]B6OsRk<TVП-{6f&c_#='A0U c-}mOnkӴknon&qڶ[ud)\gN7Rhӂgr½18oEKu$Dks]z׳5.o^[V_I]b*T IP6x 3ޭ+3U˛'V1=kk&Ȯ΅ ʤ巔v&9iYz%``{b!vŴr_Ց5AWhWsBHTny8Hh܇fI?D9ަc(d^ 2&=kJrߘMd\-vGuGuvLk?r_nfqsn+uhBxz[@Ƞty. %~p('m T!}ʁ]#aQR~bͻLXHF=$F h, vAt>A(ʽmՄV ljic'KRϖo֏ GN+0XUtVc(.$bkp+0[d_/jg+0KMMgƫa8|\m6%ՕnU/Y*fAElsnI繠h EWܸhn){O-i>^7Jy0 dI|ߕ~:q=>z Duԝ<;\?W.`wf2w/qEW* OC+z<_o.xսg]fU+Ď^qv ˖_V0Jq#vuzmmR8Zdsչkv$OZˋ5qFm]]R<dԯY:2' Ƀ\֠X{ 4+zBx[rzN?LV&YA8ʮiA}<c2*VVҢ`ə,8H/oṊɐ>fv 'ҿӚ۞6B&XEuS}w0-;<ٯy_k>^ʏjtV8{5xjd/i3:3=Ev}8mG1hs^\:p1[kG޽Lj-&g2|NE\EY3k˕f_5ʄUs^Vvu=룙דj,]h5+ZD{9=m }G1=*Hͼ?ܚsl(;sF;L3Xo &q@5&2I:w4 Zy=WO<nE,R([5JX@P_?zg榁$qְ9ktWpD6mLAUD՝32:O}ۙuxi##f1Bzǥ=J#l*qۭZU]ݨmXoeZD8uqAh* Ci,}+0OJ樨.`~jTfPXǽmT%ȠM= +whڋAMf;n 78FaYL[mA6"D][k15 bGn1X$8Khۉ*Z-g< W-ovāsZCRܑץȃ۽(5p5*Kp4h h@Fj[@ tV(R:jkkI2y]gNuu+b0kv/ZG[a=uX]RNOJ*li_[jci0[j"q[ph/NR$W-v ƨS&dMS15B#Qv'hz]HwmT59ސ}GaR$L!lE'} VA#Mn%/Q#f[ߧjMQ؅ O-{T+k93a^9+9^Z)h\ 8v8{Tn4@?f q~h D [cr Smz 0ďP#Sp[vJzKmD[Y^Ew DևKU‹` 'z;۲nhnD:Tʧ~jD}扢(*ăjH |97-XOEzvY֤&G*G fq]y_"~+qV닧^Q ޼lb QVP7B(cϵ`&(ӆI{ih dbJcХ~@{.NA[Wn6N[]:f*NOj`;L@g*TڭNp 1/jTFu㝬ƂiFy#$P6-!U@?fdZȶbh($g."\|HqD"Vnϧmy6MY!,Qxcޚ}P t6~e1$E_P}< Ȩf=,`wm/1j[r*-[?冖qR9}V~gZ\hݓ'ErW%-RLe=+&%^*T5gT7\'[EVKnzY {PHݒpS)5hI00L(o9f&4 |$َ'Z$R( e ,hcXH>`ne:歱q|@(VWM^YX7P}~2/$e*?M9*i庎""&سsq< 6tc˯N )*T@0k'8on,i-bovr~ؤeoѴeV([gA3ґX;nʜ]GC5Zb뫶gٟy^iE-KcԵgai Me[:*OΪ+] 1aaXz2V3kVgSk?z3h }ԈAp= YAbNy` !47;"@},D:M$Dqmn;U 2-szP'I";uǠpLrjT@j`I&h$Q)=Lt4͸(;L g5mA&c᮱7{[ bW{O?: T1*J-|jm@(#jڋjڱWЪO5Om;fi^\܇xӸIçپń1q+ LnzqwV۠Whο$EuTނAz7i"Tkw ֲZS$9V}ݭNN&:ȼ Ozr輡p6H=kq(A2*@U"LϵX-TV =Q=XEbq 1AQ3$5QSr1g`i3Ҧ §ҵ[f E rLznPsjoȓ"AՁZ5 w9gh+(`&!XXPI-I f4fDt۟[X2kyKkv##G.; mӵROOjԫjY8\hةrq;G1YT֨X+c#Vq#p&wpMEtZD\>5pAAM@i@% Q3j\ݱQ%v@ <=q}ȭ&#=f^:!ށŌXZ*`'(kO? ֠QQP L,ioWzFXrzm,rxhh*::9 gظP1rWȭvWY}@pc1ҹ^b lzٸ1ڹڸfRHtIQ/u}mFE'{jOm6K >ck#{lV"W3n548jl\E( {Ux[ "y6"?5Z8"F`"^MubH+cTM2(pWZ-~lFXEBjυiYS>' ֕TWI e?9w~h?y$ӕ=X8'ӡ2~x59b7P\'W*-%cTQ6հˣpuVi*Bމ <^aP&tqX wPR[qH"j M fdjf~ή+CՍ0&PF=Ĵ#~hZ8k814n" 刚&:#4jXZ 3I,xP;;? OZ-Xkg-m(R[Ӗf+X~'.d2EH¾ŘkTVeGp[zW-9-ECA5 34f!9@@e@Aڂh7沭B_,:Es[n V%o='Կÿfg#lqƿ/?_k O^Sr{SX0|dnKAeyw\Ey23n-+˛>7n+˗Qn-ݻ>.+Z's*'I[T޵Xb(H vh dfg:(m@>lݔ#&213qBVӳR΅oIke eނISB&ȣ[7`-غ,;nchkV\#4-k LX[yxQ!6`O\ekn0q[嶪!}&ɷT)-Y>:gkC Pa^>[U9"j(I.94ŭxHc1A4pn~h'n*eݸ# '0cZ%iNV#n'9l 3.LVlXiG1J<[Kq i1=++t#ht,p}&y9kL1+5hwCG?a[&n+>ZF$q+LU^֢v5li$3k|~٬[`j<.2ELe[eyשuç1 G |q6$G:|M9"MuukݭBp?5!kY {ux6X fsTqɎ)ƱZh<qvz#*^$B[A{f7cu>ֶ‚k˅ I=+.T+KbDq *}ja<ҳ-n4/ueT ӷV% d'ȬUp1qc^9;QMMZ#68UA4S"uX'55t7LGޒl]dVPt+ qڀW4ӿZycCarOz)" f{8a @6ULh$#n;B֪l? WmuU@y q^\+e 9RH'ljӤPoSz{ ]"`ۥ`3YSKR[A}{xahiRi9# 9~k4,}<}a.[f.HeO})seC &w_۱ٙR'G2XH:k>,;;d`W~\̼~)zq:{[**h.1X*jOKnBMfsA 7P /`Ahl!Hϵ^GRD%EjJH&+u ԱzX&MTe,700kRRCA`d5Nuo0IҺ]'çwڌ^QY`ybB* ųu*)$nyWz\id#{Q]XZ]IP ]`Br f@׭e\ P.fymTvp&bPF'C;Ձ&\}ҌL?I` p$Z̴P1ED(AYh"Vr ;ԷUKeXntT6Ay~XOTcډ "1҂E( {Mq\2ùȼDc@;AcHnAKӘa-w f 0OnPx/i-nUH>Vj T$Y!9 +@&.m]έVH4:ޖ!ătMҝ-ӽv}N+ʰ@0TNd`Gd4 ,f1ڶ$;tդ:جr`~EdrӘf -PO\Qipҩ6Ah],NMTM" 獐,5'=p6)?z&B#HM<4,[FѴ=#[.<jsN:J?'BJ>]*?2i2H~RNZm޳[.;G^6#m"-V0ҩlA'd?d -L[Y'5̨3ZŋA%@?h+3F=F@ ?Mk"dX+}2=CJElG#POVܟ,q(*T=DbA+vX`}VbAe+Zzƺd.Y`HS1~5;hV5ڋ.H`SZ7g{[?5 k4`K .8 |ڧ=卷.m<ڹZ:Rnڲ̊t^!z]cx̋73ETUԷeh!}@'qyFjMAX =U'.) L3& 6}qB{v4e9`3ҍA{2aykkGZ( O$F*DЭ8Q{ Qi.OAϽd3>?4n, ${ta]@Xwfv`U+Ekf$k"]ꦵS&K9gksуn"}c_S ~GlW(.@59~3]yr-yvp+ƭH1]#q>)f xͥM'+rfE\EkMjA#]]ǃknZ \zax8iB] 8U{{Qʗy(i4nnjs4Z-3 fH>lN1wMŖH]WLb&+˝RiYHf1|Aa c_@zӣ6W~ZTD͸W w 8*0#&L~h"[mDAhH ͐@ +Y2c=*z#Tk69}/ZKW!܁ 9|O}nʈzדYR1V)2/8NkEyOSHZ[MShG1^4񋎯 8XzcD βoyXt59V~]bhOp0Ȃy]BF{զ_6xɘG.5\\q،Wxоizqp=,Y=OP sf5.%c@skOM͹5gwgڂ瘬^ 2:1E(#m цg/@ǫR4!ĵAp~gh\ wfҠF@"ہ>(cA'(9~h@8鵁E@@by5`vMlEhh] GJkyX5çoFlyxz#_kR&ds5lQ{c(a#4vu8?n|dGstd=&lE!KN1_*]_qT**/8jj؆ cPKۈxtQ۵ZPurfHq u%Xj3V bfVlB$*f̑*򡢀(V"\VpȠ{M#)h(F기qP}YY+?xAo@?+F|pALnglbMfX *h>R/5щ$$$*Wۥo?l M mE'qzb5 loE0e^:fb0p{]lHnٓFnf v#0;JKAH{VZ1 Uy]Au:YQ>W;Ӧ*/q\Njjq\t &kK y5:ZyzcvhYi oN)2W#Xmw I`&y>^j@T3*uF)b&{V)NY\ʃASZ LֈK p9dݶSO^fm;T52MO3W]C'"*h +bW!ӽh62P5I#9
TfAgPзlyQގ֡F[ZK;"GYPFd׻SbkZV=挢PRLuԫ۾2(wT'ehhE9Y1@;vD2A8Wc4Pr8= S4tR P4bE`+ֶ(/8# 4mMȠ ]}&X@{O6mG3[@CKO+C]$"[ qTҸ<ޢ qFꝗ` *}YRl۸R+zj5A-zSY[tPڥQ2.w Ȩl-nUOMdjm^pg=sr(T[R\}FG=Wv9Mujnl2<梪F.bW7H^%}N ڱYKPc 6DCP&G"7ہ48b$bMnl`65¬!d~l 26hk1( lHK+{RX,$'JAw3FҶ@f}c9=hInqކZ71ҍEO1\l1Uݑ+A- 9cԋ~{tUb~k :(GđԽUZ&O9oUVڬ0yT>7ΰ>=ߥs>R-:96XeW}=+Yq\ZsN58$pzWXf8Wv}rQXkEq&ڻW5ҲܰT񙏵\,:xFUI138Rtxⵕ?X27gGOzk>n}D{<5GȦ2y;[@9q" +r￉v6I%!P OIE[1^۝w?^UdU+*zK, fJttDSb7S M`]=v+\Hփ7C\3sQ@TC:W5@;Q#BsU[KWýh3)](q'M=SOj3FPsFŠk.;+#>ո5 pI>ƫksHgڧPCyVj SN.q[Z^kIںț]G**^\-i[?{ `]O=jF&˞κEGfyW nC4 Xn !p <Ѻ efx=&gZ(2N7/VVGZҹzuߘ&}|=>7ؿ=% 8 90q~?=A,]DX(-o+yKA ~ߗ;^OM"cW>n],9}+ә(+k"AuuGP@ BU$ϵtsVVd'"FVu9n\`7 gۗ:j*q~+.5`Dz˕5$Ɣ:5fF 3ڷgXa;>TU7-08U*$ڢMf3⢶Q-AXVDE!b3^qĚDXo8 tYրQ8*>`0;=: bVI955z^[.1^sWt#wJ!zLZFTiL 5B 1Z@SZ `fG $nuAcֵfvGVZ-{ܸ\KuqH+^56T5,;~` gjݛNG=@V! juF'mńHW=to]C,?Q?ڢ25w#5|ϤRجɘ LQH,Ff:9 tUq3V œ;ҵ%sE$@1VDւL~Q4Z44c%{P'֌8ǹLAZ NIB ,"E r$0(ݸzP9@'hI=YR\v gֈ lOr|cIsp&/vgp5#i Xf%1RH4d*YF/+"O+`Sx&߼n&D`,#YbBzR2y&c=נYY ʖt>c({ɼ‿ GzYMp1̎Ml*\WH<~q*mK6eYO8W&t+/@1Z` spSwx `M xvu7C6^{=O?5# C)tkqIL@^6!I+q"$ӥtEFbWZTʩ# N}=5֜ȃW~YLyP+I3ZsOmK7G#Ca1X5LUؘET$Ռ i3ڪ(ӈ+fp:ј[!s#jVRhn"x(Ԯ]` `$T8*V÷j2eRV3`HA+dnMOj'UW|9<򧱫梻-!\?Vk!Ass $G\ꢞku=üb9 #&ˁ!LgމR84 w`di_ cn1sǧN#]i2_~({:M2`s_~lKlڹ_Z Z FW)ㅊt//ڸ wǧ}Jʹ{o߇>WAOxy6]ư%KQ]f̜2\F;U ]#Hz;B㞕ח:D܁ǽwƥgz˕8 ~fG˹d]#*vT%1jmR&O2n (QְoPRH$@皀&$1ema1ڥiA$sA_4JBGZ ,yA ":f%׈>f(!P@$YqYfXV!'k5JbZj7R"C=`IXNX,J V{$x)1-c+P {W:VT/?1orџu3J|fW%[p¢US$=?5@P ;Fxsޅ tF!n=i :0,A,L_UHGڌ2 ݨKf"@x=b͛gxjN8%A@#FaE&LV a}抆 IS,Xdr fnZٞMHY.W I#nv; Yb;`Ď\H֘Dj6.s?ڪVQmVMJޭ/ܴC/X,Fw)̈06ݒ" ['ct`v=>+/:TSxW"sZC?r>k=[쳧lۅ1)\(P8 3J փ 7 Lz6Doz0ЊC3[ԪBI+aR v.#-q7ъ01@O7p bIqA$-WH##1@=E`BիԋvZx#jz\ی ^+r]$c1=kr Nޗp QjA,z,`OJ{ѰkV` "%hm#TZڐ29:Z봤ڃڃh̬OĿذP:E){% 'Vx,%*(GLʽ;pjd1]B8h*m[DVݫf sP21U-Fk(_!\=p(9=*b 7}OOb|]Fa 8}vTz kb,Xv05`aw )N@"kH&ԀV4?1|ݼ]]_9ҫEd$ kE]fb;IDX Z6n4 E-~YEc`W!6*MA zܽm5)䍻w۸re.mn7s)7qEoν`=ī⭘}D. F SCP2uBzdI2oaAj*:Wn% ,/ʛKa1l&[jj]wmȨt_/W6֡rmv۵QM~bI֧WZ"sTE]{T@{a63jC@ѱ-1oknڈ@;[\_'#$ր.$k4}PEhkX~;T{{@=iAq"*5LE.wZ(D3.>I2t$t`|Q0 cSv%@?L1CsjS *k(s J'bT։'zc*Wkc-=w70iA!sROzb#FȑO(TV `06ȘB;RD>$HIuJhх9 y$X7{RVS\[R.%֋$ URy n(U1@;u-1є[6BhA-i^IoHjZfdm> @Zݤ7<5s 0:uKi]MLPbk@tߩf,cwn?9ה}Jn1GC×O73W<9kNkˍbj '+ͻz蚭rcޮ"5*W/b#uTN޽Ɠ:ۗ*h ]\nbgďe~V{!_zcmBHY"Ҡ:QY83`qڍdFMA"F3EbǜE:{V`["(3ǽ|?J3H Z,dfDP4rhaq~#M 5;O1MISD95%ɸ'kcPn^y{w ngZ ssJ*(bKONS.j+dYpA/( @[P ϽuH$``esLQp8t iN'F\D:StqvM; e\[p9y`D,LOQW)W^$59X܄ɮPT0 WK=>! WPz F ^->cOjr5梶3LFj*l +]lfMlWOJXUӏܴ?CP=~*#ckIi.X&IZH ލdZ3CR{@^ yÅW+V ́+rqdt#qzpL+Afe`EX` fUD@ @*AbŭLj$ڡE[_5PZ{];Ԉzibw;i٭yZ[i ujEv=F&yT}[s,ѽ5!`)FznΉds1E-iS4b eFv>k4g<8Uڡɭz iۆ#?j69^Tq浺qTb.-R:og=usR-Z09AoLgU}ۣ4A;xJ h1uc] qSAmd;)>e=kѾOV0$=W^\z灃jU+^nV Tg!|L X96դ|ڄ6p$wd+{I;UMtӁ ,uΒ%5&1n Rڍ] qVc  t ZDqjk`C jNO(qHRX5䪀Lg5{vLa YgYĬ 9Q $q@6,PfVz+5Q!tƚajJ F`]faen(7F<ء-1Ҧ_QlwF#n ڡ8"j D='J5\`& (HYr_hƏ0LQHnh }?ցϵPa2O f., gށy5X9$$hw?jTQ&(1#Dm$:6Z$4fVH) eoJ+(?'@`c42y`nX5[#&Hҩ]s vN,(7#FhIm2F-1[Z}Rb;҉jXچңv|uLAVzTZb V/ȸs>Fx4ZɊ!p S1J-[D\+8 }@[D8ߥeX{Ԟ tmA5YO1}RLbh[U1BQz>%f֥#c"YGHI`֑d256eL0Us.o[2|W][OM7`=榏i}?mzGCҹ׼3d[+BlǠ_ċ v2(]dpw]` dI\w7#9_yq2:IAeMuι=Nʼ 8# ֋3Dع]ե,3挵SW nspf?V9Z>ڄg2p8rķ;31|}ҢOJlLWXAiфItv*_yOZlVEEb2LsVayEn&=)>I%W{ [Ǝ@nb^?a]+(L*{Ԏ,q ֱHeya{{T)?^D^%Q ބGa@ZӬ2ju 3C7Ss,OAץ0EHStM(r9 @ytCN\1ëkc+C}W<"5xb f8_7M$ʐ\>"^ǽMrhd~ϧHԈh+u?5̪F5!'6#ځ@9Z3XG'y/྆_=qHrD_wc\ݧ8,&b}.^E?ZmmѲZVEbL}Gq%u0Yu|?ڽʼKbd'jQ0'޾'LL b!Mz#akYm5Mw \Qu*I籫×,9TR ?]"( Bzף[GZs:Q5THں'DqH' Vaݯ'.L#R $F^/4sF! 88hjJ)|c޳T /5 [d(WWlIY[yR:(Ȓ:Q\*wgP5R&P1qc蚨zh\V+OCdA{Bnfλ?IOI_ N ] X Jf;Q5k`H+R::u3IpZEmJu#@VbrۥB™( wa"xFIbQm"  slZZ] eL.޲h\BbIM͕ ޮ, ' 2tcᵸ`Z\=kCЇ&HMۀҭcC!$O$V؁!0leڳ Bn_fC" p"j'1N(FGZ`B'ya:lU,Ycz=@UʅzLw*(/zSvm T*1]bv] ]MrNXfiƢdNs+0gWp^QbwnPWF&,I\Wu ;DqSK(* )]IgڷSUjMnJ0Q8gYTc1[EJ! |TZA.jA ȯsYwl 2fq\on1b'*<"T+FkH?jQy"֊A^>p( ր9H2=h:[-GSXՁ?z. @2f EVgoE"l?4""`E0#KOu$(j=9uP'G6tfEڭ ,ٔ++5M=";Acsq1tTif 'rA#n] x{Vwњ*91FU ؊5xa\V9-@7ȃUV4j\(sVq<]"j*̜\$=@oҩ .Kb&oJZD>[:w(k2DtcL gWH?켌QA {N|"jH3ҽWUa@ SvqWkb*neP008btoAԑ۔5 6.z+PϨ-JOAhH(35Wz3ʊ2]uye'iFDcT'(¨8EI )k f\F@S~qLbOqZЖKxVJ3Z$S8=E{՝92?^,[7ʓnx%7Bͽg8rw ?&NwUu5JXMR Kh 4H1֤nɎEZHF"mh%mwI"zEllFb֩-&sD$g( ngi@812 Q[c0Hݓ(7}<AYL\j,80GJ \ ,[[s~($Xj [ VC=A2 c@E=Y~*Ѝ%_BD "f(8 9$(iؠDaj nw~ X؟A4Pv&ɣ cBrҴmDb&(h,U $(AqȞki8mÃǵc_z0DP z"*jko[[_S0Ek#CLPy=UoT>[wev s?k辏5jQFg34Ǽ}˰Q;Nz{zQHԚTQ]V0Mn8ɻdl=G TfI=9~H2937K9\sr>)$Ƀ5T> IR|ONfJc:!0HTXnUI R*B.p$-]ּቕҮDW5y7`C $6GN+p7]dǧS]p2TfCpI\r=묨SUST61nX ؋VE l LDJr 1$G⭇u jTLs]yK-̓==]=Q0qYb΅d hu<`jj?ڹC9hnMcLL+FEUÐ징nk,s<؋IZm P[ճu,̜+*iDR6GC(by\eVS b:Ķ&ܸ:Wm["`~k/nMyn `s%TuNS-\d+NIPLXL.Rˌz5xV\ѕAv}&?VPEb*;ˏyg"Z}E%<6F1UX,~g޿5_W} /jڟRaW꾃tx*krkx5IpA #ںWQXAND\7C1"'WӅ++5NԎ@^¥Hm6O@k)p wXTҢnki]Ei$(X(*q( 2g0VZұJ69ҍ'LPE5J!s@'& @AK~Z{wrȮ?<'Qt26s&?tBĶա戶+)U8;z.g,JλF&w{\R]UX+-&XϺKzDn)x4%|H=`9n'{X9KZYC@7h@]*J>k`AUq=*EYR b(u slbP_(ZTwffWUA1 Bִ[aHP0$e$)(ldW-~5B&'hނ.@A?l Ƙٸ Q5\L*,͑mLG'۽H`g":QDQ|@;cBnzP5h'MZu5EZ=!1W9жbt*Cĩk:Nָ9 3<;ӤDڠL1Qj-I#BŖOJ@HZNڂfUզ흓 =f {u:n b?eڕMI4kv]ǚy&" wH{j,Kn1@ձlzNk>jdq5{t[x"j^e S [-=ՁdP14Ջsn zB΍Yr}tXo%K5GH D)\HyHh1BDk5=&@"]ytu]Ba'V\\€HF,ٵ`ʄzsA5M ,bաiAI玔M]F%3ؚ3.f,`zX:ş[Q b9y3>#sFPbOޤ8\Nzk"Oڍ ĈNAT^IMl{*޵XpH&#q䓏YPYcp##iTfdUV2bH?j":Qઉ1;֭07' mLRidON(K3E+`We,#HH#=)>U +RAV%~LMl1h<)˨'ׁ'-->PW̟jG=KB<\TBjmn1[}KÅ]yN)q^\Ʈ̩Q<㹉P?ݸ@"8AQ{T M=- @R6|)ʆ' sY@l  "֝Pg=:sYE6Nb?j[OoY[[rb ${ 1F>wOeҴAܲ ǵӋA&[ t=ǽ=uqT"PِzuQ* 5 d,^+FقI(lhTmLh%i*'ڀjHހz q FH$UDw%nҝwOsFj c~^n*ʬ9Ui%@$GQ3bך( *qŲMh+"iљ#3PB$LQXͺӻsݪXˁVcv Xh l9"HPUĒ$‡P{ue L;uBU6Nw1lRQn-PLF;s@|4NAՋBwu4SjEe}63z싹YbU֟}jZLTh _u*E;\='Q`Tئ#P P4?7sZڰ m36KQd ?;W#}hfBn6@=ukumz>]SZPaq5*InoXd91$Zv*C[!H@ʆѕ'4-qֈzh<"Y R}n 5Ss[f" c"XVI'iA'0+ = `{WDV o1#`Y\g괡9+r,s]ebƱVͷ!f?Ʃ,ʊX0P[ Gڵ6|@VʹeN҈\fӉ?ڎc^3'V~nJUdj {hؼD13+u:3Qha1+w:+sj]}0IA52t @<x&H=8NdR5ʪUGb[jTLɴw4e7f8Z/= 4$ϵln¾bMz"M^$>߈^oA`AQST46fk9kɬQFi ф )-aS+F>`ѽx޺s~ww}?|,tkOAȯK+&,-*m1ucpu#5ƺJ&V0H'\tr7[`u:ʮcg\Qv0:) Mr H84RÓֆmȒE ;!fxia CCSZAXځI}t挣-.#VڹnFZk.LRy-$̚ NaPDZ&ߘC uX䞴,!!%$Pf-߽LmF~Kx ިGpM*e?zÓ#*9kTa:Fi,dtU{`Újq-Povɦ0KX]j-(F0I]#mi5hl$r?t53jzάkoy'ˉr+l&[[0Ҥm":[US6,Dw1V`U yd$r+M$$JztڝĀ;^95mGZ w ɓSzVuI8U[585:`kՃڧT, õf JBۆ 7z L{`A+V2fdUAaYI)?v8VS=x:'ͽւb>(,v:;z+[Vچ&KL&kjae@zMOVZIZXU$XZfOޠXkq '&KDT7Wp}L?jѸ=5tz(&g4 #dh@+x`w4*;PMr(kp>o\m%ު!Ȓ85ѕ=cm*(7m ҵ¸*4jzud qCD71ކ<ѣز qUoN.'nl$>,rnߗgy[A2H5Φ-݌5kHպ=j~b{Q.sFm^XQoY/bꑕT~DPe;G1h]LZbHPʮ943{XkuXK~k ;]psf!p?m0tr#cDd]s?O=jھj=4i#ѥcdE˾U"}[nmr?:vGmuV3Zv!?jWG=Sj V7mviCe]Lu㯽{vY$z&WXi$DG8`d13+SUm0$48F"rku-fc?K@ӓ 3Agҭ9Lm1[b$GJb+|ckމWԘP@沶rmn0VRmH=rHDY09V$Zµ7n=ֱcM qbG6ꞿ֨Z @E0'sF$$f] oތ}ZDIG޿>= m*?jN;{6AXuw BOj&7hVog ~cRy]e)21Ҷ"^Ϟ*bJ3l6+eqtX|gD-,8=#C]&ӏPPż8Pp"G0Z,ݸanjLOZ2` O}mHb E!!aOz2ds@WT"ɉѩ$=MlB։rzWmq9Ǔ*ZqjbnYW \Er%Cj.\TgX,8DFM Q&F ڤqDkd$[V\ j_{ڡ$8̜Z?s@.i4oҦc2>E~_߷ϧC[lfd{#AW,S;zXE=~y{^6JNw g޽~7.u, n9uAI ^ʺC":#g9klz(3X[`I1ޮ$g`ܶp"{W*A d\BG'MvV2"+r6q*9֕**ΙWs9яw&5*[l^GOQW۠1\;Y V[b9V!hm&L54i,cfyrL@d3ܚ'CaRՕg  Q؂s׵A\dZf Sb iAN{S G TiLz[weA?ڪ~_Թ!\H}/x|-z;Z#R)kQl0LP2 cW5$TXԴNLu5΄VU0GBiQeL崶XyYTtsJ^ wǚ{|l=WvHz\].1TaG7`wL6 ƹڢ.Lz{sSY2EV%C+504GJ7\ǃF?4@c=YȠb$ zV (k`:Td{+3D[ ܱիXW:{HYaրmne[zfoR+k[ÕnG,q 1Ro[HR9gۊodz =R?ucBb>ԱZ6է-X! s=lnn@{hPpzP$ʟz OқF fq7^UU[l~jmy kM *=tvlێ#VyNg]1:^ =%{N:A7Ua7)i\fz ,:'TevNY[n ~'z˟o^yonU$q:vnV.Els\Ӳ25kwx1.YH>đX*WXȭhW,~#؁goU U+>nXKQ}ʚ[b0N o)[s;8=Zh]ꢈS֮E}z=p 2kJCZ\`}="ZFRdCOw^{?5->VV,O'TԦP}GJgW3bX4`Ե\As<UQԊ x$J́wB#$br^+qA9E\ٺ ,;Os׽pF U)fCƜ 3&~(&0cD+43Z>gCsRHa"y J{vVI@DB͞;PH3b^pGj]?5PwrkDUn1UdptrI1+C;Ye1OD9/u{H?AxH_O<хAGV:E0yS NgZLh]z[CE_XMX#n#潜D2g"jW lʵj烑qaʺEifikS}]=$}\k)Oiyڢ,d<\*zuWEuK\$'u/bOꙑ_WtoI'<Փ|yDuvSQt971=kBHd{$e$Lv@w@R&&޾@;XN!ejHȘMz9j284Vvn}sm>}!]$JlqAGQe\ ֡QW@63cΨf,zա3T*eřRP) (FֳHy֧e6 ڱe; Ho'iܙZ$怋#2Av OY**n LRGmCOhZnс# iX@+u&h,N;bۉ O˨ Nقzk~ۤbmeFOjY;OȚ=35Gn(-i\Vl⍭$GݛE@`DE 3z}xJDn Az(Tll@!O,9WmŸ2̓D׌W^5Btn%fZ$lͩmB+nbԗHIdsBkTfgYV:QSfnA!aCFtBh}+2'ZK>҂˱1&}c4J!;Ayv6TGS]\jZ'3޶"tޟN+X,16k@um)j*3.?XS^]YDAX#qs?*[ryqYPƴBzPHVEH5 mnM`YV0d5 UIh6{ ګjk1x[ V1pAQVm!h+64RZnS2E[s>acp(+\ YZM؋p QVon#<\r׭y7 89֢DRDj?jZr0?`A?4WǸtLZj($!nc0z>7T[;f+0}I#oO}kzI@{7@%hZhJMH"m{U`DEH( mmIz *'S[1lSa]*=۹nG.:c<ز T8X1@&@JՖeOA.9`= !ëftb:VX"$*$uLJ晵3ַð#pQט{w(PGU`zŖ$5 nة=楸`740xѧa& vHTqzTwF#mH'^/b晗h#$OyG}%rlZ=Q1#㮎k"Ұf~krW.f\q]ù3]"CT+Pg5Q4 u֑|  9&kzӷukMmZ94aM֖aŽκF&C9c:ͺdAO[5a@'쨒y'~{z箦AMl m5*=AX1֤MUCV`t,+yaLq[ *hU W6y 1!?QGZbL889o_0I3ު&mQ[K]҃r]#iXҭ>CwqҺDSlձK׿X$# LY ƵJ|5ldNw} z;A021Sp5Iz'6B"M.|E!޻ӨڔDuY Z}(kD{ыУɉlm(ejܸwdf굞yN P (\`3Js&컨 46C744`@@͉% 3P.,2Hj֊+5W3(߼x?jkY7@表\ IU*gV_@PP z2^ O5j#WW$:R_xRnBe=ph$P9چA{`tL5*1T'g(G$uYPNfIJ ݼU?I' $0'[ (9X aI= yA'K 5I;ֈt@$:Qj6hBfIqFrмX ž ]"-X[LjΞӛ^ 8?Dh10cz=s+hgˈe=⢮W)ұlϷpۗ7m[ qNܨ"H8u+''H uF}R>(TIOJ<@)W FThL2ѕ/3p ` Q=Jvh> 䎟%vҴ:Z! K1%`c5H.O^AqڨX!D,&?@ `%6V ڦ*L{V f {P3\8-yJN[747zQ͕$44ΛX2?jMY\P7cH& "5ҽ*bO\@:k^f3D+m9K 䁜ւǵ S%3OeIjF0E56_f[z֙;pO4]. n+5 " [O{-˝1²Ha 9$YlxR1|J﵋hwGS sR;q5VQ,cTZ]PbW9چ[ނaT7m)ؓvO⩆umަb>S{!BD:IXsG:('\NU`q]ch鉶8zWT+l;?zKDDVP6)`qe`0cT&Ik+e!y]GY!kG0q1 Ub-z0} 7p~ tz7,gWW*۸ vEuשZT-cY`:Tuk'Ev%moܚj:] tvܱ&y:Z"ᕕbcsiIlr Gv[v PE.dTU.+޲ֱۖ˷q_WMZ1MX]-&[jn @-s~%kHY[_́Z9dST{qZ4Qqձ?Kfen;Q! ۧ梩k'\VRfDc"OjHx p㹠 L[L$.o'5AwϽ7cDQ32~(Ҷ6_DdU"O1Fvy%5B`9RK3A`a)S6 TXHhҍr?HFڔ'o2kSFHCViLl:`eW{q@Ad8 ڈN=Jnfն-Zj-oRU/b(h~P=(đ}hN.nS3֌0R"7A5J2uqm3@'5LȄPo+F~7Gu9׊VGj[!i՘LGCڥ[0+`#mk(e D}c< -}Ѽ3#7 LR`66⻋3tj~ܱ޿k+Z Zmbj`c5"r:w=ӟkֽ±: {7^e[۰澇1CY}|]#Uɓ'Uc*HLQrŲ2Dxn"dYHє xMA|`ζ+\;#>99W{e;D wUOWnS'$ϴWDp(8fܱOJ|GN֯MBUkyP#juPe"k  Oh8S݂O41S-H5L4{fDCK06 I$z".@VU};q. AB^+N”ڶ×5u0?UO9msz+u،W:[NNsr3 54 Y #PCTE`Z85-ٺ|ld?++}ZHP2ww!}-m=b;׎.D?*~r#p>hד}Se!5L?Q[l z8s*kOnCK@Wh$uۅU듟ujNjtͰ7ZZs.̥d\C!6 uk) khi#x׷ō-ˁGyG1ݽ/dLe aHi:ӶɌx汼` ҸNM ҡ@3 ֱFb3Fg%F2(=Mҟ ` na2gbl&hS IAySVIns GZuA$P%CCw(m;+S\Ҥ@Ѷ)3F%pjE|X<֧lR❼l}O|4v`)p jGL\ԅC$کꬖ1sr0vX(c\lv IquGnY&mB`t5ƻ@Z:V)m j#sLCHV/oy3@ȪP8 !@Nbl0k[UGˮP :Y"=;*+O+ĺtsp\V6ldfO %mL A X >MIln '-(jmVVeqڥ guDR&3 PͶEXo+`¢@Vnc--Q?հ;ZcTĴک7mqq=n1T=1NT j8j]d;jZfbrG+2qދI *sDG$` kp V'V'i!kDH*\sځ˜Fi慦" фրM}`Vm6T&뱶JڋrXoj\"H;tu;N`&$4RM lnkܹ 항A>=m:FQ h,Oހh!t0 &VpqF]C C p чH{d XHJECd[b89Ȫ$ cXb)uDq޷Vq]'.u~Ųhm4޻sWmT(k9mF]>D~*m=''g-g\K~yflso"5\ڳ;mMeZtݫC?ڴWۺ t`vTzGz@1&/*&;sPj6dYZDT]RMcak)kEr>/pֻG |FI$?G.&Lv^|GZ謪"pyư}o3ƹAaޮ9{$զY%v1&83]ŝcsMT )(ȩZvF\OXhڭa&~kqD^Ծ0nJlOJ9swf#p`8ׯw\G^VCw0\EXb'"9X qMf uh GJ0Kv@2q墅R xj~X[s׹MRvI^+]к.u}U}7(v GQ^\Ѽ7T\0e ʭjMƶxι?M݊OSc\kϢ f;v{*6erI>5C==Ārh$+(mŔ3ڤ$E huHQ5mcXh&sD$If3ւY ̈sIt= lK+t َ /rA]1 x GZ3n0 &?9T}UƺFw7 :W5#ud(2X,MeV*HhPďzB=C8V7;Q'˴kIox5~U>l &M=-*<2}!oҍ=,8+u="ZϪ.f<uQ6Ō3}E {?vh #r<֮\2Mmb7tnaxƺG%-$Nsj]c>rt ՂIڍed`śp9\GKt#Q;s Aւ@PbD.B33 Tbd \ 4!2sڍ41579aS-aUoEp#x'ۥTTAȠ<9`FQ8.?5:/+ v&x5ii\:m~1YE 8?5tp(74wAcPK0 P*o]q$Pc4hOb::}ޑ*=J,PO^Otq50qiGB QYkJݦӬ>]bjp;D0䆟TB+1;\MNhfQTěNkd4!QwL-E%隚WNl'ao\.>dBR9צ)e@ 2!Z+Ms]"+TZK kR [6W$DJ F$~i[9!ciaRXun"ƝwGRrCs'Q!ւvu b?1 _ԆgDF`O Oލh*jh{K3gAZkgkL .-|6nLHݶ.8I94 ܛt C]&C|@-8'&#o6ꫪ?5κG_Q5*8ɚ;{Ρ>pjmTh5qX"Bni*y9[u~E-5io6Woe wurJ0fiFhTփy !ս2D+S "uh&>h#urNp(&B&}`-6+ b[0Ot684 O&'޳DRⵖdaen z@`7,G3;> 81@ow>ނE x D*6OJ'k2hWz! G3e7`k0$SxB@8RѱԂ@17Sob"ۖ؍Tz@M21DڻoG$x9ӳR>+<.F7]RdF6k+Y3Й3Q[׵`\U~:|;]fQr'@vH HH }MoioxFtFpN}~ rL+5Z.1,Q Z.J ޠ~jXO:uľO|}ꜼW $oLuwXn5Rpjܨˣvh{Kp#;0[h'n z{`(`E7 <Fb,)2 IM6$Gj!b9,^F}tOz.}+k?0|$g]uqUK4lWXZBɎ^1)F5)x n,cP 2[fOJL5 V IR1H^ʳ)"""I'P6 VF8Yqڰ@Il`n 8$Hʳ`n4w>ٜ~=yv~iם'wz֥yǴ\M+cuqj\kP@MBW2:T F&g@$, /EHW㚀IT'ZTmRoDC{Ιg@T?+jc[䪔ܻ_?͠ď^N?[,fO=}Z)R} w毟eBԟ^@kxyy{6,ޱ>_W;G^XZK4]rf#6$J:l􃚶6hqqƁ*Xś#8{gEuW(9Щ}o _G{mk#ػG,lPmZ,ߦ1ޥQ.>çx5׊]pDJӴg ]3".#(붪\@a Q"z0ּ;jk^ޥ$YJ;>&ޟH#qBējDOw"FÊhH(cޅ0u 1ɃXc$~k).A5R/PC3^y|^Ys &+s^ &kq3]qC} Vb\iV͛#YGJ=9{|n[T}DDAכ^V'ށ2+kj=:gGiV{ČڷAkYIlha@\hIٲ`i;`OJj#DlLB;NOZ '*CvTE or[ #1 qFu,T۽8}dM < ah{cnj؞|W40 O bgѺ_nmiȑQB$>gz qRcn($ Du`FDn! įjөmX&r'@h2('nu˄13[O#ڱXǒakB@O}["*'0O4ne 9Hj=^5xryzu&Kql`ŋwџF7V|QwG+&oYSh'ck@7V\L|V+kGf&R0OJvDkKGZ|^OZ˝rz᝛dvT'h%loC*q5+k V{WdNf;W5GW AxjCܸ0T#޺q^k`v35QƴW{&m80ۋm~ک4c-IhŽVcD-7Aue\$SV7|ʅ&s®TՋ7K[Uj FbVV2}?_g]sv;M~wX^7xTŰH$F7ĘRo_VșA+pc⦉POiQׯ怪ޟP^Uhx^?z2"&~թ2n+V'rظDߊbsTp=D.@fk"1$ʡfd`ޱ{V$VOjT];:}#Bjj.j %Ggo >j+5bŐRipAֶ4mX c#4V收A$CQ 8"b~k`4b~+M7Zg1T: w][!rԌ)e[L4MQcߊ;H 'lQւwٌ1Q:!]Ĕ;AO#⩺Gfyw_oLňbխ˅dZ3uK0ViU9@zP6ME+zSU7>oC\)(VUlnz 8cffG5\/K\\txnj=Y'3\G?v%\vP[ "IX$q147) <1V7&aWX]d;O]i*%C`cu0`2 UQ;LT-b'ʺG;p33\jd` V:+fbXTbq>$ӵ #*ɉJR{{:cà8Sp'ډAy'8@KD ܚ'luVD|U.,N(4X'@{V7BjlČU'wDĈm+t1ְ9WϹn9&[1!?,:(!xmP 8fEҋ;Zi=#nLb?ݧpE\.Gfvq(m--] 0Ӷvί1]bj )s׊#JrtWg^bxkV7m V]GAQ3!"s[ kiRA!y+P@{azE$$w.'doVI< k$9C/$?沴ge' :B~u`S5}sXz@#Ѭ}Uazuv_ q ˧%jpaA]NKYe<҄XzxX: o(Cں8/ysU{J/iJFy\`֭k|yU`s[uxό]v0IUHԽRm*Ce A#~&51N J{3dž $w5Lq<=WmUuԘ<8%z+>0*fI1\sU$V~:MN :Ιx+ӡʋ^#rֻ]W0y\^rG:u59k;*K(#sz\wMܳC0")j/vc:@*IR1'U->*Gc lAPFbD?[HAB ph38Fb%`b6*&"']Ӊq#qLv/h Rȧ <~=Aom`W|HB8Sɾn2AP1K} u o,yGԚj㛄DW<>G[$+s> 5˹qZs"k+][`IjG]c )e"18NhA|T؅(}T\Jn@'n6O_$ "yNg1]":C]ӎ掳E`d3g+#rSlb5ͤ(Ӵr(w2;ן5Qq^zNuF݊T P+5qE%Y$sހ`#51@uhN Ao0 ,NO7[x=T eICt6QsA$6kju6ElR-LԳQ׈$geU$d2CKuðB3>M?5_Sp'yrFs4D=Z\EF4C t5D[ $L5mIA$ޘ sqU M L5l$k܋EAMy{PNӋIMV1EZ $1ݒx #¤BH(YxԵL T  ; u ǯ#ޥZڪ޹Vf-==1zͧ$޲bۙ4ǨDVE{?Qk`p6^s]+U\w46n N+M][)ά)v. ,6ɎiK[%YYtMtC‘D*;!Ӑwmٽ=CKqA1߭X|BoZ{n )um?֦OH$T2QN .\mU+YdmV@=Akbvi } ="`((+ށjHV!}30 8=6RNxTN1E!RF1{5M9PYŭۈ3 zҢ@䎼PUm$'dZCrG<"^bꞲ"{ΕO-1ROKJIuG{ϨȌkeջ!@u**Z 3RՅpoh\AF`q[D Sp]sGxlB kqƨ-|F2Oj,XI'4=ۃHbWH,۳Ʈ" DILq% a߽X MQňXBz)Y3\jHe3[dfbv`p&DGj^py‶$զAWGZ)5t?@>U ׮ܶoލĬ9K iY31=$bVI;qZTbL3DpwւJd4 :$0Zz.ǵ Lj z**[<3OkS ߨVFhOl#oVyf1pL.jPwXcwW)$Vm6|AX*SL(@ = D$ BM#.`hl$ߟhWiI>^Tsbj;STkX`#yl[v~|M\LGT&S{̒"= YZ3]b+d/VW<9-V[8W7ѓ³~.?LEvU c3]#R9W+T/鈞9+VlL;?uҥ@*%}꘥v\B[*&K-7noLŝ#wJu *` s wJoSFnM_,`~kuguG8B3*A'vc5hPUX:F*;WigUW?>ߜH;;޺9vHMtA<޺:'W~\kL^MQxKұ zGڡRXsq_c1|jq$F¤RisvjZ j̀b ` EdS@BN@j=z&A;+nR14EMr qWkKt Ocpn]ց'p/ؠ<9?5r^,qȏ])bO?zVɼn5%Gڦ{T՘0AAgⲰyS?qP(vR \oڲ :~_k?:ޓEf͂G ,~{|W;I&~k:x/LN7^3KSDMxz&xU~<ܸpWG\^ssxzm] Lw*r IY7ø@:rqZ+λ؉#  k74TdjyM #Q2`X\7Uuj+[! I?>hel08_Z>jөRZx}69)X.Nju A'x{ysF;W*ꩼ:zt7ȩV\eD1 I Db(3THC7,g$ҁ,ʃs8mAsPؔ֘U,#ަd2Ӝ3Y15 fCȩKRd@,&ĹQ\O8P* G5⼝ǡVy`18Qwɮ R+)b \g-[GxbfkGY"QoKs77?p1$ ',ZDDUDRĈfڂGZݽ=p۠怀ʓ(%0A `H[EcqsTtRA:keu#5?#A!t횰pf^v>ƬNՀoǽlA怲EhZs*'Qd `pga5$ظD s'pb`)@8R:-1KLլ)l \QjKZ$m⥘ 8?"R$Lkǒ*4pI3U-8G $5thiZ+, 1xj[+l3޹]9g%[9mŔt_?δ bIЙ /nF qB(e]F`>~k(lyH j<޴I Q:eYIODn U@aLO$Oۊ n!P lF moހeSbāA #O­NZ$p;U: 70 GHC*~ ևY[q8k5d5#[M|'[b(^BZ}Tb]>h.:`lRAG"c޾.)fWD97+q0Iι&^̚ނ0ߊ溥z{]"jF%GJ5-umL)5q+bA5HEPT$,;3+Fb廾J=&n34EvMi_OqE9EnWmUJW&wօG$PWDAս:mz ~{EMrqDrh֯#44P3=1jCXmlV1Ror z)"+57.x:v,]'1KqmIL&dYtMN9cJ\k RSA`p2G JmN$ZZB㱚Z/}PfX ~j-wݻnn({85s$nukKaz En 6j.ō 5=薕PkbZ6+sU2I58Qb__T;Z 1Yj\oi< sט5޸W^T.[,f3ޱK.G߭@} I-ǽ-f.Ozʢ,$Sz[Ad=2'I2sPf ӭ=$ȥcGPMTd'8UO zLпv`w%F( v2:A`԰$Y@րP:z(%e rIO>BmmQ4 mUdGX'.Oc@Y \}yh"LA t&7N ? t:Ҳ@s^Bv2:x]o(Oj@RX*m\%ĞM`N\+R9&A (br=[jV.y<6`;+(F9baQFX3zGQpU0zQP~ciLX2t$l,\ KG3#\Ӈ;Q_ɱR +-ҫmqe_t{EL"-s &%I‰$ eHxs]_78MtUn*=EPmm,G*|_T-0}#^$'2\s ܾJn2NJnF5?lws'uŸ?eFxa Esan!TkӤcđֹKU W!Hsq`{2 ++q5#Sj,nUƉ42!~o>{WֿHYkvDhWGٳqcnj[a?jIPnO&:j qIBDw^qWp=}|%q 7o?}.ckŎ_]şv qUbA0O޺% FzDf'4 zءEA$hZ<+mQ+ lH+Ncͷuu}:~+kDŭ#=5;˨%zj8ȠZkuӇnnn_p9^^XwUnyWUv ڢ$"sR".$n}e g4RnEIU$Pԃ}z uP!I1${+dԶsѦia?5HKsYB݊V$9Đ-1=MJ&AwFOܜ|קм+^6Rd⾇:;lQ5qG\(0c#L77_yzYW@޹ , *j<Ĝvj>d)h 'V"] T‏pY@~Y& OZK$[DhD15;L&w1W57 D["YQd,ޣ#"=ch䰓؁@mdhd눎SpV*c $,@P*PWû3#- 2Գ+&'DC[i6؁ީaCz$A?x&P6ܙ$c e fI b-Xf.)u<}[[&&ȕyw7[`{HTʍR*qqW?e բɶz >ƶA&s?is: ߗ|=>s\] p-fsh.^kCڀN(ҬvL{YC!=X& $<.? ,[՚bOYDu4wS>3Ҋ-CLH PDu=hw#z{hUqm^a2@[ PKLu5 __ø5*l&3P-Zd3H τ] BE{NA?ޢ 7zL9"nZ2Tֱt![5:?#Z*_vwYV1|J]2x=|j\42b+uڂz#YgOur`]jޘ8sFk+c P'VlGjf`O BbwBHb)TdnJ 0KkQа1+STv@*Oظa He*~#wj?&ckf V @n""zD|$ Z.mZW %m3(x=RYNM~af;QQN;h8{SF%С;XTŦҙB`f,5F|* T:p+ BܼUI@o_udcF|WIr&hx=^ݲI3;]dp!vZ +08y69-o35H˽xS<*uxt$vϦOFYD'U $B%p0 " ٥]uWx%3]>M,G)!tRW˂n?N&}`@grT@ϐ;f>hؕd1 L++H[{Elj@'URH' l14sqGRU4ӂT-p1ֶAHRa܎@l)+]Gk.í 1.ZcA3VWi$Y 6>(Ln{Am(Rg怨-9DHQꫀyۍ=E9$g8@t,+,s[ HBAnکh{WIgÎ,5G;ZU#"jn AތdZW:g8}spV4ZY"L{$xzJ(,=R 1V Qv1PA)$sځ!qlL[ ǜw[f ""GX؍fah{&+sV{?LPyd,M{ŷqU~Dk¾`ƺk[I9׷a.=Ꙡj3|Bn&7p\Nnk4hjW#F􍢭θ[vm\ǂO*޻@ɮu7O&Χk_RdUm?ӂ!Oѩ`) 6魢gffKqju:YDnւ@\FMlW]Ea]&MjTu]W޿G#ꯦtlmX=]z]a;lksP?LՕB[Հjz}ϋYfL;nZ&GrX`2pej(g%$j!%] `CQ gPOjNi1'0KSm=%@? NbɈCX j FJacF%)h$Z0q@@IdR }A;mGOz6l\[e8*=Ƽt=6^,H\AzIM@b?j CNjq vsI8gMp"NzX,6ڨd]b=jY\~!؍ıh]g^wY&'jJmC$W+sMuLkF gXQULLQ V‰70qTVW(ߤt\ āߧDVZ 1DY+u?J]dz*nIj+< լm+\"Ԩ(5s@ ֥UA`LQ7ͺ >SpMn*+Y~Ղ=m8)bN4J^.Jp((ܺmke$JS951;-4XV\k]Țlbv*;`֕GUkn;oKUHP-֦Lp~?@ Y'sG,N \z9Vݘ ZkW\ zv3X/0 PP}Ȑ'4 ɐ$QH_@#'5"|%WY]:g"  =h9/rkD<3\Gnu9eq=stA̮yEdGg׽8 *1mk>@[;LdCys Z`jA<1'. 9=(͢¸'\pkc Nr:VwuʳuhX\K>QLzUu+r WHCsa{e$=5"ߐaD]b%75΄#j tTcv'6r=#$h]ƑՑ7] !k4+P1QU{Mr`kյNUi\W: Cs}5A޳ I4_/vx{~[HǽN}T|C P[`qAfF[ȥXᙫEze@`ׯӵ\ tҽNxG {u\Tr>,^y93^l?ڸWX뛠7P3cPتHV24^A3fEH2&jZJZTA,[fQoc?>77>P,'|⽞}}5Yd$2p ~#JLNpWklC=*T~ASԟcX\L}μn5|߼}8Q|y" 8*μ\+KxbFz:G% GXb672' s1޲8-Xq8ERX]#f]vgb2 u5 ?Ꞡt߷!y-UtPy'U~?<~kWcI_&:txVb߭x=Q`'VLa$9m8mEY[ Di\5M(`)TAVB8uR)k7q vʛm*zג50 6S #5ʪ<\xzcm"3E  ,iP0=$ c4&j*=u {PÂ"3< 2L L,X r-A {-޴3zUNOW%@ +D'ۊ 9Uu_Q~H=Z-[6D M1 WqSCҲۂmzԇ*\K1i+u-ܠ1dGPLcUƤ6 .W'tr?b ڶ7De|RIL+ + v扢S25Cʊ"3[,J+s'o/fjiў0ǵeQ^N) Aܑ3Qr$:7N;>/f⼮ k RhJ2L# M`A#u[@pE bVamVVU$~aipg޶A;d\gz}BےDM`5j3ED@ϽCR$z\FOuBaFÇTތOaڍkwO?zl_ YjIw}{Xn1nZڶĂ`vZyԩ>h/Cv#B3Q]?lAȤvec=FkŠ iey> /]^d o]uM-P@wOJ+l%$~֮V$/mrXISRVLZJl8Uk UPޫX d&:Y )G2:TU];=uoNMlCN,6jsS FxZƾ$\ -`XHl쑶Kpkb_%> :9[~+@ꉴaCcz \mPȨK.;~RހqV-f4vlm`}hk&[m~՚դi2ё#i=/6\+@E?f\ A sr_]Of>*-t3ֳ$z;]$l:V0PHC.(n捆k[F h{њaU [Z6uk*v-ҺJK]S3=kq[{Mum Mh2ZxZ;$Vtk,dJӯ5P)+TI{Ѱ;j\3F04qњkgjOz5>I3 CfzQU +D0y5&2 'ތE,yx8[ v`tvD׉) [.!gT$L"Aq[BDڵmw g>Ƃwv HeڥA%xfF~hC[L4b,^3NIFN3Z"OF=om7GP\I8+DBy?z ә b:tg;EuFkv Xک:sx$c&&sE]&:qX<ֈO^ Z%A%=' 4f Y /yA'Z؛`܏PO7  G7.TKg'pIOx*/:ш|fcmg؟j +HJgǼ5ʜ6_OZ=juznI0[MzEތ~i.<אJ׽g1-m6ƅ $9*tp{h"`&>ћmvG<`ANiRtk3@UYzY ckEd/skr)x3]#g kAuxγE`">Gs]#H.?Q]$F\묈\<3ںĐQpW'jCj=fW^P"lݶOzkEu骻rI {W˕$#X ,yeb\y\:\?sQ)RMCehrn6@KU۱ə=*uy'ڨBA'e?[-Q., h&:Bx:T`B4ʆHҥ}6$w1ӺKYpk/QTSSl_*N3.,I=+tokp1=Ij8Lh +*D"L}_ 87;m[]8qu @|kw1$}2!䢪($ ?Uc<7Nl[0+Wk1XגqR.ª DPx7>6F,^\zo|MQ~O}8ZIz`H3z$]" +@5Z"m*OMflXDQX$A[V+݇q {ϼĊ#X3/ʟL7 f?LQ^ڿzYt1}/^VrA0H>_*[һ\|v6<]glߨ>åx<-c+\`XuגqCQQj"dOboڤ q<*p2%=CfA8m$k}\T6H1(70EZ`I$rh+ <4 fW@P bA"YK'iHVB:sYXf bs[-qa{+so:WNzqlz]KE6xLJms+gӬ.a=~+xݕ6͕ܧZݽ~9ig5?B7 ۏzmv9QQG#h jM(;}A|={:s@6ڌl$;Q!v׽.J-5BvidAƶqVI/s5Ĭ.;"w{ %ST,NqTbm6;o$wLpNC(,4 rJƀ#Ud[J=Z0H5nYcj{F阣(ָJݕARհ_ݿ)=jFF# m!6jкWT`J~r!O_f͛SҽE\jmf[P b/h ⣯ʾ\{ ׈=?޾\`+ke  ڀV.zc;"L{`-˛ %pn1FUA }$Zb& c@k$En>~+0No0'bo" G@UZ x$GAiP fJԋPVʦÒbO-D5> TfԱ_:MQnz\53*S 8K+J‰`zjf1[$65qQZ%1 9kw˧8Gz𠖴ŁyqʴjXO&${*(u mH#Z\ lo5ajPӝ1H?6]İ"@IXϽ#zMՑ~ pGa[*v(V ;Zl^׳C0UdOh0[LF Mј =\;˩ڌtڌUJ2cVu-QkR+ ap#2EkU$\Q"|bɣH-QbjWAK MjqԄ`$j#]rׂ sYkÛhm2OrG8uW *? ;]dsڍirk`;ȉ&HđJAMA1 NfMh%i hEadF m^аcUbڻ`jmlxm[?nߗ:toRκ4r &GkXfŸ xQիj$JqktjhescP*H\@\ cgIJ6ԗf0$b"z+C4UC MR3w7 Dbt g=MPOEg P$m܇7quqV¾  3` '0E4(O~Ղx.}~@ LN%bXVkmFc c3҅ 4 1ך0xwr A 5R}qW#+S0=;iZv8;/޺4RlN*YymZʦNYW+E+ sxRçJ[mb-4nA4ti8 b n9m:4q7S7j +6LQ&Y6\I;zrMfr.;J w,A?&;:w^h usP(N,{wW~8u~55r2x?K]Ĺ=G=ԫỲ"wc\`_SBYO5:żX4#kJ|3lg99@[XT)jos$ON+Mbkz4u5QRZO HY9p'tʃwP bn9Z :Qp-$X^׭t ˧&DWXˊ㘫Up OJ$n֌;HsW^Q]7PIEv0X]yugW6- Ls"N^fZdұE'wQ\W` W:5;uI2>jo!@AByRیf).ԝ<vЮ)#ֈ mCI5-ļ'N,2f}Lނ =JߥjvWlJ]Z/Jn@WvzAJ=z׭m+i'Ekv`w}61uH@f_ڸWFa,zj+s^ q#YTAv&2Qi[RĒjߦ,ku6˃Oa\zkj)Рhn*۶$ߙ^>?X+? 6vpL@tc*`q\+sPFF7P69Lt3E `z^Y㺐-pJs_ =K?s]rһHTwҭ57DwT:Ve9cXIc#;2v r QT5 `u]#Q1'®9Z=zUiNJmx~Exc-VP !c_nGʪ~,-8YÂdTX[pmF+kqZApOLQm idYjr%=jmG0hQ<@s~۞9`>InEymc59߷ 㖢S9]eEr~!ửT2{ *+x.ɴWkL]r'B8~C2}=3[SGQhMPAT ^;*-1Jlz2DRqs^D0jT\VB t7gnb']"k%8ʳuWWXkUu /XXM޺+Xz_K뤎u A<]dEdILuHof']"tY W,4>ȓ52#h-L5`y-0H Qy&?j]qwX4g@k;ё`8I5ή;`&)8u9vΫBc**+ךƃr٘,=O7p hV7^7 $YjP㨡Xr0~dvLA !z|UǷuZKS#@` QCZKnIDj:laݤHL[\1\ wm3¦>X9=k Ƞ;% jWA,OΩ)}nջj6g1c5u5MChmOGI=+^NʿCMFyv,L{bqmCÉⶶ>z]@{E9ׄS`. 97O<<ѳ 8=H6mUH+VuP}tEV *橆PA'ڶP{*6u-#Е'3Z=ˌ0b*ZZw~$}D2d Aޯ˷1]"/*'\qS-jz}zOD_w>"`f XW/,^[-aqTK W]}_y^c8 QE<D ܣbx+"``{InްD0 w5".`@"c(@W3&"- QD˱yj' OI ְ`byjn1z -6R(, SYɬЀ5!D cQ-}fj.CI7@}z=Ξ_4mv0c}gVywl':TyύYV. fI5<⸛}lrJ](wRD&I&dG"r=F$ 8#LAP$~ԋn2'z\'3]K1+bJWW:z$HF}]"hJҖٙ5F*F6~hbU}b:Q":w0k^c15o1 AgoPBfMjUwn+<NMooHf&%ɌMts]m٣;W*j*f`[ Kinc\&""#4ƠRL Q f$QUw-;OFx"#ۭf%`Ȝ։.>(@Q=*QSV̗JkT|cm4$(B k#oܷgn>*-\:ō&ꐠdIUG0#E3\$z*F8TAn2^Q8#ۥcQ)D4bTymv4̀:TWd{с]@=ҌMc ۽%MLX+[Z6,tN2(A@]?JZRmL 8"xTG9}.X! !y`s-p35%Fi-(ܢ'MI'hU1F4Cs(.) 'p8^أKR"a3Ӡ]@6ިp'AbQT( A*ea<@-zVY#\CW:eRkj$tszH6'PGXx [cvO65R sUcDhmkb٘p[;q=uXz0^{Xf- J3 $'Wv@B+\Ed\rK9]*HSz#-P]U*~x9Zkv ɮ">ZXG=djFøWYcN0rMu>&XI9925zs=Mv,%y2>k9НV"\v2 -^%xġq3ldsd=f ݈!j6$R[0At=n<]/j!X9V0a5³^Ѱ $PMN7X0? ݽyRhy9KR oQ*]P@P1i955i+n.cn"zր1 P p FP&3",^X=4I GW @ 7ދM;Sڽ1ZMV*gRu+sSңYu̓ WBP[r3*egjU M-5Cm"ڧ:$b;fW{?__ƇCKovq?_~q2=-"ZꟌ]}#36;5]}H2y):.-$mw~--y7 "E#yzq$fXl9#_BGMːXMuzp=tHW3\kD)у2 r Պ/3[TcK`]q5cp E[2{QWIiQs+^ڷfҨ%F;{SUzgY7--'_vOd!-D{x~XD 3?j=]ËLȨμOnq1i| Ѩ>nk$$P%>4 nek"> JrG4 j eI4 `AP1:O:Oj/62p(#qvYCR$*c1ƚH935Be;EEȮ.pga>Mvǹ>UL&ϵUŷlPOz~Pu W|8 l k]gY TQǞt1"Ҙb.m9=sX *A  %`G‛dw63[q郏z GP!baH HZĎk+Z-[;r9E#3Tt]1$@K#-*5b7y挧 =^VܸGڌ H"Hm֚-lڄ>@a׵n!}ۈ@#8hJUv+M3# n=&'qUZ㠦 S2v GF,D-ʽz#9O[i_{Hʍ0{Zydnr{R+j5 F8-P0y׻ͤz${V()&D9f§_5d,z !u#pka8KR FrQڳSB-wsv%z*T x &;шp 5''#V*](O;ڸ6OA!`_=`c7=:Ԉ$$j)iTZ@TFz {՚ wk($ `mu*|'X%en,2 -ny΅Bׇjª:=6m,Du5-lHjlOV'mJu'\Kj9 ]cOJ_tEmG>ƺG4ነ tJ֠lL4g™ 4y!&!OJRn*I2@4cx'")|Sj[S9q-޳BVWIvjr˺LbU{[}%W2+PvZެPGAWMiɶڦ+]+qD+݌T Tvb#1..OѡIAg r$Iԃr NllWP\@E(xصQ7?QZ@pNM<ƾ[?DkkoyDbc8V\TXaPRbÑ>J㝣Ӡnx\bL@Y q 9 HI L`h& {ඤ &4G5G7K%']$sJ,dA`a&}?5'T eHR2uJx?I-ĜMsFIyZBaKY穠p@@D6zTwTJ`HQBEK3@E\@[PgVĘ6Tu!wN|7KꅰGCygbG5lve{Fn张0, םaqր?ײ99-3֧E{`164FjC'wAfjƆoM|INAu.[GS lHG:gۘ u"CZ&fDH݁]MvQ6UmğAr@u @Dƺ@.e32IܺXgoA8CuA8';,}5`|Q ;-=(bCT P ޷@my׽4Vuw[ܑf+**%aGzhC3xkv@$zfoLOokᶎe~kJKr`_I;"HƮ&5MtdZn0f1kLv+u<#̍1ӴSRvWޮTj|4@E)71U]uGNգ6ӷbbAAwX {1;KsWHmJ0Ds5nV5Zΰuc}uʱJa׆Cz#]2u nӟ#Y{PX"=:7.Y zfkuˀs]dG8 3]dEAY#޺b4 1ޭF j5%q%ⵁIJQ6X`V$Cm\0x+gԧ3]"]IYOA~\wٺAwyƦ:$ɹKCٳ{HMs\fkάuQ]Q#XX"pɺv50`-l 0 0)@g$L 3ւH"ETA;oV鰮nHv}}ʌȁ^ז "`Ԫ8K*OIvBݲA\jd^-rDʺ@ 梨JlDB8wBݵ gU>Lg#aC8,G0O_}ޟYՍ2 rD#'+''x~~T95{jRp^g9f>p&ťU^xqX(b@o+}{`悥HzQp3=(@av%B(%dYEbe»L):(03Zʒj MF'Dv4±jbۍ<RZb :PJXa"y"#Uܻ[Z]#کFP 㓐l pWZV5Q%#k J[90s[;DhDBط .I+2h\"K[~ݽ lle] T+ ]ښk g|AbH9* :BG3)fosEy>OܽjkH'SZuwrPlg4+zDN8H2P\Ro̻' ) ԅiXyqXsҍ[E R1j s?ڔGӑ + ՂvPY&}0GYRLr(c@q$qR(FWʝPŭ2%`IzjغbƬZL`Pi6'=?J l ΁osb P\_m>?9wOn4mD+]"ޱPkHl\D?vuwK`}Mhto5Q6\5/iuåe`ֵjoHUHݢFRxA1+`9_YC#h>`d8iM͵guĀ? 3Aj #h$('C !WdCE@ ӽJJL{A du]b[1Ij[`y5"ԗs=뼎z`[L$2PoZTpB 'իDsIz>>OJB(w.4vVD H+׽MME&+X'Mf*&G$};_gA1j +Em8,73TMegEc"7HaލE@~kc)ڴ&6&%.$^3 k,(#wC 5.'4aq2gڷG}+}ZK~J~9ޫR 3=65@+u8еTi'NN*ݲ8Գ*-]-~q B˝:HjKV(̚kXa8\բ~ob=fjL !zۑs`+]cxÅݹ`<^yn{Y㬬as]g1u~4n1Vc$'JົGY޻NQ~I:RkrpD=걊jUz^@LeEӵ1[vēj ԅm1iӚ3"@@`ւ݋P&z5b%PJ[(!'ngp>`y\uz&rL^غkY.= dUm1zR1F\Q{W:{! I'ߥslOQ[a40>YbG5yb AԈ-=[#j1 LL?aCL940"T(a[>hU`\emoNFfz@{!tXJ'_E[Ql&I>ձ q :bMΩy HZW n=EZ:W'QlKD&IO-jK6H11_B|'飡-Rw(Gsݼ+D( , ^zxht )c^EKu WOb:}a"2W8>>?y:ǐJ! >).*̆"bsO czZdDЖGzv`El`+ʜP ީo ]"kĉQsk#h39 ',;HK,[R1jnSmO_B~׃z3PVv9_V9f5H\0jU>t8ު Ԉ[XY@2x aؙ<ѨOwnnRL4 lPAO@60z3,gtqh0juU&$IIIڊ2(D2Dѧ%DO^h"ˊZpݲsT&L05<y|4'Ynໄ՚Ӎs_QYwb^1Uח `k^CmcަD$ J-qE$b6w'0G ni+1tOZhJ 1ސ+W~µʤc9V 􎕱m{I`b=qV}vJ)`D*HzVJWjJ6#MP\@;z(hͻҪ}Chk^AxZ+| #[[_Iۑ@mKhv! !{-߹30:퍢}sZmleJެ!Uem@pO&풌:zx`LgjF6 scF5kPɅQӟ=ӱ%ddL}Od]sw2,<1YD/vOՊOzR{UD{V5;7 @QzVX!or<,Kg,BITHFk=8Hvh0n ;8?1Bn56Cs=¶. CF"eT (AaT]4ZQzeV=&YbZ-&`X44WϚd@ } `?%\ZTeZfr~"?!J>F**jJgu4cuqW. {I @,QYiP0ր$Ti|GrVKWYP=}E[C d ^b*C"-C䃺 "5}3wu$Lx5QmFDFso.*n ŊpH[*[BA?j]mө*W`DӵFb18 d  ؕVDX*"*:43>` A^.*)]$p=3`dqQjx1q#5WîC;zHsN1Qjޭ~jhBxnzP$7CK@k1i x*S BԈ'iQiY_B$ 6M4d6m)wQD"(*L m+"jj@>h4;2=b>= sLX$3Z\V*2>h]@q?)ݶ7sOJXZњkGE{VN;03@tp($dzDւj$*'hSQPwEdM}` 1U}Q(Cd:F Iv{H~~("w P؞$KlVND)B@Up2{z ̊L@ȸң=z3g("o1ނ(I}jK?PJw) ޮ"Zjs+>Wy`߶kFYn4lTmN@Hv": W V`=t;80r;Ԫ $"F:QG77*jR`Y>1Xq^ U04õg JGJ0fs޳Y2QH+H'XkY#iNxWjTH7+ҁ-p1F ?ڀwJ |Ѹo5^e+pAW?D'H<6ڶG*@m(YFORI'jk?Su չuN㹌VU7`]bY˃kn#XzD$+k\jKK]k/Uܣ }Gpmڣc:J\PZL'>F/>k}GI5sf܃0:;uDtf A>pKw8 99gFׅ}CC=:&߂wFQ7S޾1깏y 5ߗ;U|\sjN9]Ċ <晱ÆADI`皬JRI,D0g!3]$B,=$je8 $q[[N5Khz?=}*취#3_ _@ k<[~@;u5>Uz<um}=kW`ZsiH2gV]] (Ar~F ,cF@w0,BP"O&6 FE ;'h&?k sSևG!CCA(>=@!>dm8 &E@'4RLcg& {DϽXLRP}5 Ez? Sx(\Fђ3k;#`}?6^99cDZrhI{~zߘpD?sRSa%*{ NX$N#(̋ DP@zP˻2IFV`|,*(H(6O=hqBX50ґjcUC2jI@KnEP$(pgډ_qx:$kaA.JqHUL@K⌂ٟnjm}B[Jn@,z*lU`Adڲ-`yU+I {FwAhX ۭ3 % u f-5-#TPmkȑհoB̐LT gTI¹2&DݽtxEPgUzEIR7np`bJڝ,# sS`xݧ/m1M~{?b$`2"kxs mjA m-nf {P\(`uzrrt*\δzHFBIWU 2z"*CJ.A3U׮J\0~nnuzʫ"EZTuK9ʯz3GT"ZیPI[e1&lƌМ[P"H*# jdLߊ,D>6E@]dq++llX_,NۊhKm܅Ѫξ 3"]'h8捀:8 ij4[HvW_Ђ (ҴAQB s4T B6>9"c O&.8,zE0Fdg5ym84 %U vPh lCw,ks@m#Z5wE@sވq_Ri-5#Xdd[q[pk*ܴO\*XNdMߺ*) j;/%<iێ jY&_E Cy"@YLڂ \l"MmC qwK-P[hb.A? [}3Ҫ"ٴG 1]q6XFϖ;{W~c;AEz[(@ax恵wE+~*m[/XkU@.w \mZiH`kӪiZђy@%;.'zEf I{+lUAJw4 ˜hb3: X<&ph=GL1,K8kAdI<6nPE-d&jNKdP &h;WmRA üTeT ]#U|ўg?5r&3$=͇XtU#+-A 88WY]|* 899~$mNY8v睿N]W'0ffܬg n7TC6lGdy[ v7tk;iؗ8"#:T9Lc2?Mtb|4a9uJ'FWz'榪Mbz ƫ]12yY[Ђ[vR'h#v"3@+ GAUF$急HaGKp7r;p@GDzuׇ.[Iq~&6۹&jmn9{y=MEsZSPz\#.~`Gn↫L*=V &HiNݒH"<[?M7l2߯tAA޾G=_zo]C?#~kG-2 ڴr]@:Z`ۊ;+#?4ӰSM2 ZJFqTK+Utot fQIz"z"l(}RiW^}] 1S@oP?j؊N۪KxzblTH3M~z"LIr+Ǐ6|Hsg+?C7eG޾U}'=uzК܅c\ V݄tQlM j3Bwx恝 iLځ2zIz"aڍ^3qY0l։>A`N+ wc$m<4y k#iTѭ9 j%(Sq?":܃a?z@9Ӫl`ҽ+&Ǣn.A}I#-GJt\aj@ןxƽ{mVk6"!ڤHv Tp7H& + 抉9Хd&EfVB < ϲRw@vo"{P3-clϤIR j$-*,8h[cO~&bjj]A U1-Z$mhUTzGlц*6c"XawмydzUX,%r(,`pYVW aqݚ &!x=ªvŐπ}QMp dҳ]]"+wCvKL} T ]#Ru9P>JDb91j[sοV8='35nWRm]ܤ¢浘$LX3FSg916S"H_jU%v[d\, B!< uvpqng޳ p"i֛y#kMn9# j[ MrnmXE`>QU@Ooz-J ~hjVаQ%'sYFݭ@#OLT9ڴhq%yEKmsTbLPIxΨ*v=M>q]cZ6CS'0}룘5#$yUvGýBX;[[4[GQDxx~,I0sAg[Yl% >hAAHZzvh]O4VHQ^9,|>HmmpA&o [tݣߚiܰ`E~[ B} }M0}HET9M._ 2*6SmKЮ -iN5pg߰ 5p+BXW"+6fٜWIV8*1=2M{pk_[<*`ף6}%?(?ahO[qYg5C|W~O>}5˭6[Dt~<~myNZVY,tNQG3|YU& 82;4ȓU\d]V` &#`ee S4HDH}-h`Z(B785U20OJ0FA0x`qXP%N tdJڂeaY=S55-=lhiVκ.@ܧ{ڱDjr6p֧TDF03"jqZ;TJ] :Ent#=|HcSU0j`)޿Eo%K1Jj0;:nf`.%p:Ѻ{~aUQG&*qp#Aߚ*>Qj1(mX\GqxR(UVO{OM"գ =?+KclotOtW+t=U*I@OO?LRTKFd<yxw_agn[wN~J *F~3w_w>S,+@VPWov<舘m] WiKF{HW?Si |K |S<3x.f}75|mr'x$c 1浅dVeqPx`e J&: HSG3~@r$ ++q,\,L\{o5ۈ#u 7Z4@ #($A$iYL*bZ |.`A׼}.y a9//̅ҀVzRdxU]p6'~G|wx0d'_2%,~bHY[w6(5*DjmO D\.9YP0Jn0{m73znMaj1F! CLh@:m``jd"~+D]sP$rNLzi29h aюᚖ"J fL! :4T7|ZRݻqzrW=+s;5#98]3s\kd:y 1r\@[`8 ݫ1^L )-(@Vh\ܜv4tdTp[9;3˝=+`[|+ ȟRv4I1;P F:PHB$Ϙq ȲF:Em}۠sYArU Rz$"=|(nml [P $= ى X*D`w`=36nh;N+x P-$8A4t,nQ*U 9M6P! Z3Ɏ*Q[<]Nfsm~;WHUԣӽu7}>G;MloٴDuʴю ]47S*,0++mqXحan.G\v58*ȒT(A5԰PTST)v5U^ mPlVB@r cNul[o۬WH}Boک4'btT7.ݨ ֕b (uP'M^Y8lFh|OL t׉.OuQ\k $EG>p88Cэҧ Q[VB "a_m-cZCk}On08{{VV¹=j*ʎ#Z` q֍ٲFN4jz{bqV; #Xn) !O~];%0aނvtnf1ƹl-&(1=}X[phJ _PXhXӲh ?56:кUbbH]>qקtx]DJ8\o,c3?ڰrgh ʸ%<*:ޛVH;@2DQ#(>P.{7S khX PRGziU s9 7ClTJ[xeW qnR}Xkc)b@O:[rTG+DYӂO&ms Þ 7-0u;v3pLR7^nu!A1& Lb4Q^X[#RJfNzsIR>mkV،J~c1h 95 Sy*Q֌Xu)ҸXkV?5U 9 ]}' ONAA&RqTf lx? '桸1cVlG[g ia_W .-D P}Yf7Ff8 PWt5A7\cȖ!^c}DF޷Q OhӏOt;8!=1FIp+?vv&k[B WYsW'j9s;!l1&Z9p_r 3^y@̱os\q>=5zW[PY&@?j<n1sቓ+3WDa&7,=W/v`gU릩0gYTW&;6گO'3]1ӥUH@WDhFٸ'[ AZ&HєyV"f.dvZZ]4bw#Gn3iLsFyRJnMY3ލ  DБZ BFLjz$g=xl )Ubj-9+JTH9ߔW[񫊈8f0G5הWKח0fscޭ!:mn,`ϊ\ L IRQTϹ6KlzMF5 zr&M0#ڥ %*kusGe[jdjmGg8tЮm:'++a]`j}9ax\2 OgYGC$qStMHuZ _SO ^jW '8]#1I1ɮ=WHva~\֖й#T`:63Ԛ3|<>#O Ldz~nm9!ґֵDdtk*sNkIRs@iu@3k(`!j9[Zbrl{ѺoNR`;{M~>l*ҽ<nO|߷b{:H d\{%-ˍ݊5Y.&4TYVaq;PR#o*[stΫtRIOiҰYkM1a4Gm2stsUlV`+q" FA=jt+V6xX.N9(w?} f\ UcNfI`+A|aMf 7ыg2>A2*gఀ=>h25|.㰁=He'tmHTq^/l(c#1sZ&DAZ#@/䅠_3@ͶTl~h`>kjF['ל!G5ETU5R.LGCED,؆'Q.#OǨy" h-v3x۴$DbI2Lb,|F+@HJ&A;yF/uC3<~(c@%~fD.NyGB-.Qz|WZ`P9~K0qE+5N9ISQNk0H rAuuK6;b' /ڂV 34 N뻁`?TfzԫYo$Qi|셜F$J} !FERqF] 0+˪?M$1e#BK@I$( nTި3<Ҥ8I8jnqږ*" 򶙓ⱩfHEڰmQ'_qUm8I0O^Z$Ȯ+޹Ī2+uvn㸑^8w9p+gn&#?/^y\ K;5||I>8ZZ8]ws:Gs,?I5rkWke:}JÎbuzݹ7mЂ ޫ ON9TBހ(܎I+k@Rm ۈ#QLngJ~?4F6 X.4EM r mntae"N։N^#G ^M"qj_;]ktn =_[v.)u 5V%Vw$I=~sO|^mK@_}N֎ݽ:Sj j-Oc¾wTi{:MooU^M"[WLNr`z+0.L {VkLAس3P[^jc=ڰTg})SuW]mn*^#)`H7/,#P-\H{7sT}4b'-(Lwz`)? /`5V]kb{ka,=:]j;ZXa^;%n3ON߯*USpӏxl{qqvbLf( Frr;ѩ׭ly`c F}@I$I1@N1qRȁzQ;Cf,obf}2i))I> 5@>%HlxhȨ n y= 4 $Y@2Fa5ew̲e& a^x:!9$\:<I=]?zsWXT@ o5κVQ,drh8T3h/>qSX{T`,ޓ@1dMeV r FOZ; $Atj6M"hq'>e*CPHNmM T*O}JDO怌%e-5;ZF+Xf=^ձ&wI'5I@\/y@ 'A!*5Ŗ6h'כn6`nGp+Dk1CfYX4p%DgES`e13ZʹoUQԳңWW5w \@m?SVʝAQչc2ȏvAp*:W?o _ >g~m9=~<ğT25$(f9L]S7n\‰ \hkh#r@IrV:=դ %PF{$ۤf=,iڤLl*16T|ƃi`w|#ǯYx|DqTAz}Rkqi5ѿquzV@8y!Me^[=@ֱ~@$ "YDP@NzT]GI1<|M'.sl r>/mscMŻtEwYnKnO3crfgۭB7$LBhH);ČunqT1!Q[W.F#5d)F&Zu @3FTb6P X6 iA8Ĝj&Q.*@4;6Dw5۹< &A85O.l eFjmYY҂L`A[FpYW]MlVOzMvXWV5UOl-&K*G.2&|WHÝ͘*V`1bAT:v7vC@ۉ"3.X{P" 8=0:'(hbws>\L|؟޽<ƾ}EּRH*`sO~[ӖOmdd׳-cW/H*8"5\!9+q:`뉷b }ۅ3 ~("41ZՇ׭[P6pktŷLdM`/oBfo$T1'u5:ݷf~ 7l1rïNh(b`sYT}DHo$@(ՏP}}:ӀZՆ1 ]:r<{( k#޼}W 9Q1\Gfry0$E5OK#Zp sT &\uZ?4LA9'޿AOMSgr_Z)mYyMqsx`\+{bHX2Nj#>fP3Y1O #e#_Xhm]X|w_gx 6V$?z\~1Idi NRxןVU2""dOY~\m݌[<|yo}BڶdӸ3ֽ/<}ly{϶ Z1k輌ֺڰYʌa"eA'IA {Ph$։1&&.*BgjeM\jf_IZQ{ӨZ0M1_|?'u`` ֽ=}GAp9c &DM|7xgTrA+լ]BbPj+2XQOEApN 㸩c@(DV[b. ~@H⌈cPH"WP04d.hCF"I2k4H9dHYDF95M*#~b h$hL 3 ?Ӻ5TuT7^ 厥n2}k^vGxSKoΪ - EtJ Fk?z %V+pAM,neJƦ+0c4QOI⩃529<3?ڻG:i1uukc`X[!q +m,=۞Z jjqzqYEƵI1XӢe޲+\ijUMG58μi鍧\{W@G޼{VZ->ǘ=>+TmFT^ JKQ^=h K_z$:Eށ_m f.$ v* ;-2n5MUNbdz qKm"=,A A7`㞣3 XҌTx~I]b ?(%{{ &H ڂHz,If̑(+_P@hHOsUUy3vN݁'mwusmwt+bo`FqsOqM\ty!/qAR2nۈU|7AP%M( y#ӉFMH`'_ӋPŸmE$p#}aCz 7" 19mTv#zD?z  ӽh${T'Kg*q?YSH~~N}_izѥ*WFa^-Yk$4hvW @B`B=(:@5'+sW~)e f8z|*m/HA9zr/ۺYX2rs#{|y>G^pIL5!!p}FuygݎHtN=-Ml-Br2A]buYm\m9U3R}+YQ+ЂKъE9q_ک2IrLx/vyQ7dSp&zhmH"-Ϥ3x<Jjnxye&:Q:ڹ "mϾ}+I3T2{>(Z-oPthjM%w8'R_£q) UD gj pG" lTM >A&퍦(+JG#H6 g1T@)괈GZXmaD) 6T_L&(.%H`-7=(l:̯$Z[ܥh%#ް:ې7`;OY23ލIta$Fݒ)Tg+uV-k *>(4!-0%׎{m ^<eK=GwgjʇYjp:]=XRy_U[fnBqVG.$KNEy\z%Gy_gmnnYxOHx#S]](D$WM]}ɏ~XSsh+BkWZv4L@מahr !ܬ V}Z>r"pT=O}OWyx\vkԘֹ[^}ԎT ;P5ш&}0ù4Xc(.5dF:u}v# Uwr?#5CSv8rcu,MVn!LMf3Ү!T#(v"{%~Ɓ4DfXa#u *@ַG_Oya x_|.k݆tgۿ9߫uMl`1<|yLji?hy"񛛰OQشǰX Vb -nzEd{R [  k5Aڷ7fK4FLɚ1`O@l@ɠMt8K=AR8a!!4*E}pVg#m ?5Lj]%w1T[qh-fNbݙ 3Ri2 c [6lAL=)b3X@HpyϽ *rcݸ$R,ޛXI6E"O5sGP^Бmm~k0h j r 4.4e3X׮Ce\ET^fZz󜑎9RR5"tJVgtj6ؚKH aTU V& Yj\Ēh._{x?bѹjV]ӥF{)óClFmZz~h:ԱmwX贞"OPs]%sƺkmWIYޘWdZ֢˻xye lr`*GNQꃐdրIF3ޱkarQR$';QZJ DɷdhJJmP xi. `K<vRdOSļ靽YR vzʞ'8YN?40Lf U1Bߕa+B%Fւ n€lr c4Jd e'G =E"[{ `! ޵:sڣ jx'Oi<.څQl(Ln>T8еZֶyeXk+S:;UY5G4F㨂ۏQ-e)^Lzl+,s={UHj rXx OLtⲚ!St'53P$=[=CSwE{5\ a4^]W4;z9^tõ{VcD!pj-))E+ ;dH“h%roD94al , JŅ[jX&f@`Kkk񊊸h |N#LWelOuk>ۨ/䷧ [{W,WDיGJx?^,lZg=ߧOX{pf#V_8mN֟o~.*ذo w=?uQk-''OF_[$1&'޿?կϷiuR OnUg5]sF ᬻ%_n'BD8lXƉսݸ OScZimUV'za 9C\?Tu,;{UȆ^w2;WYz,u ڦf)s$we:3RpAS8h.h#{v Ic7O塄{UqҖ3Ix>V[H= ===dmJ^O׷jY#+9˗r?jK,$$b5 Fgpy9'X$5L s޴6YHϵ0E㠩$8s@"rGZA@ʹ4 'g ށ1dID4hD[̊tA1$!hZFw]A x^#hgzȥ@0$@fa={W:pn\rgvLGB/|Oj+ 8k(!0csR1MP@?ʡ9BZĖ<'j[ۡ Du_TQPuDVn`x 5H,?j`'bx5+ U 6ɅX3<(yLtIg?z&b3V^k<$bۊNڀdˑ[%Hkq7)浩Z69ϵ4فXbjK<ژo_$ZZ6S~'pcozBa]#Y;qfDo*7s]%BI[jۧfHn9?`@!sۥx|wW'0=+(=A5֋ {ԅ#%h5W/mY"Afz՜X T fǏڵ5<Nb!uV"֓)\f?K{cg39'7{Il63n+9H#JYW]K&?^޳(Zc]aw=M" 2*q[%cBNyrzH2 Vcur2{Rk[ME5==3BK]=ld &rEu5zt$t 6 ;?r KX]"+cBXOP*DNJ廌=/) hh&RKT-'E<$նF $o9n;U1Gl!97YV ziS+WC]TVΡ8#Q7Uf{X~[ůcb *ۖ#h6O5{Wh@62xE1p楩!p1XOYEwSnY3ҤGgH#XI X(XB @ч[ʰ83ځj6mڧf@ V%\1b.ԄzhH‌Ӝ~f8r6qg5ېš+w]VVA&|PWr,ډQ[Z:Ͻ [$m|Էl[AhյU+`7Nnj{~j[G@G |YB\BN99F a$P, COJXG@qFpKqPM\#D ҢvPEdթmdڂFќ[€kZgVAnAT&"3k+`dLzԵ!hdR䎽"LȠ`l3eB% 6P=Y_UTSk;Pe rZL7`{G>!.nߘڴUX=v9: D|WleNI8+Y`mqN #ppO-޸ewFb[!ndTd='0  7V_4`7ߴފl[m>څ;Z6[ lmIIn!8DNNp ( oJ?4=ˡ"QQcE-@4`ؒ1!^v*;jy:+ &޶dAeT:exg\s~yu1;[ł9(;h~T@Eh"rfWx꬛Ŋl5 Z~mAU&Z7>,.V? yVăVң@`#Rj 09+A.xGָj+T5Z}Ϸ";*keg\mOXn3Uu@5Qm\byjY^!a ~B)Tb 3Mu@E0U6۶92#^(=:QR]DtzU?GY&#N"Zr Uarh;U6̃QZ$^~(GqQJ]-ȖaZVQF#?53v2@< #ufꖵ5BE(QDSoLqU ?cw]? (e:O'yo9%ى_W}^+9ҸWmsAst\Y;TZ)*aCDs$G&5 lϽ`A cC cX05!oh@3@N{6ǏF$ (yI̚$PD(A-4 QM4Ez+O Dh 9ۡO]}=Ƹ p{^U?F6g vtb)z sZ uE.9 @[gl5yBh" I@Yr(C0}z#ߵ`;@ĬdHՉ,F`~q)hӋyJ@[MI#2_ؚ|y nO_jڦ̟Z TNUj -āץP8GkCBʲg0;ۿ(jŖ 2*Ż.KPA.@ հ&`t,e44@<hқH7LdQ"ݻ;G^EC:@˛I[XBL fDVޏO$z`ں6""9휁j݋|XD}kQp1S[}'~͋/9_gοyju`R*j$Z+VEٵaF" @0zTNkef~#0>Վv.X=9i"JPlgֺG;^L%ީ]D.33[-Fc[bزOQ8MjJ[ Vb.HVn-2)ct/( 58F:ާmF$^"}Oޥ=EUu.NX6Nl -Ŵm\ǹ1-˷=*gxw;銩x#k6"&ӑE[oU&/0@y5il[)e0s1&wUqQ8ghA zPŕ LYR64ln}͸lEaTKl vb:}5lr9'm]2oR7 D⾪+OҘx́ 2'I@kϹ`j$z S_ac<}5)R"0*Vwsml n)媙^GԵq\cٻ1[6n:d(8HaDTx"7XH$#h\Bw d@P3ᓈI lwn+Z[6 4"h{ѺYiI#Q+_oe_4")dPRU,(`F:ʩ*9"h\h >p(; ][6 31D6uݻPu"+̺yzFIf$Axl19,%Tz•m] U7Kf3w4 A(jV/=;Ff[py稠,#.ݴ;=hNݟ2G4Q2#qm\VIY]=âJϹvbDH[[nbL t %JznĆȪM,q[k=U"ZZ 8b!vŗPc:WipD wΎbP.* gTs^י;]maK40ǐqZk-[ 2{s`XmxV[FCGn7*ik"V{a80cm=d$bOd@ @=&n!bsPF:tB @xU-Ahnm"0#w4HV$*#q:U؜ՄI1ҭ{P(n[|mdI3T6_ OW,puNҹb:hA.Z unFR Nڠ3@OI@KR'4hާh}>cJMi-ژ<9ӳ2IvmA|էQKKLY"ഘVj ޖU%dr9*r1l)G@-}n? Ċ=`c".dJ6rrjuc,(-ň&X:+8:`tۘ{k,_FPQWkxֺ9|5t.1خƻ]^S]jUkV7IǰƤqP7{W]`ؚ)[qvOhnF9TumNi+,Tt?_* Wt슘QVQq.pVc] o.@&.˶TNrYOD 5<\tKDlڸ(U95B͛l б`*V؅Xw53<ыb}CnYK;KnzW\T~jۮU-Ӯ(Fh\`ȊJ YD` tskmr0=ނ˳ǹ$P)@܏ހ0Ocb RA$+$ ļ#VYEaiY(ZRͰ?J,"^=uP$EJ}T? %JiuDB[u#,imځAӊ!x' I¶F~#+(<Ub[un SPtU蚅@E щڂn+0h!G悶WU0/pzORҸ=W6"LJ=` OZmv~<6xWH竚,=D)+o*w 5xƙY<~bE >IXט{(&gMdlY7f;1 [Xw[HA$ӥIn\ܸhج3bx%X@$.sŻ#F.7J}'~զnW*qXhhw/Yl<њ%a <;Dکd W[!p邢Y%j=t1]$Mhhm.$"6R"-T-El,2q!DT*-lSw}rqLZckUhV 15ƪ !yR\7H=  # PUA:~ݖV"I&vPb4h}mqIV%r s@5 g#@bcf )dD*|?FE;Oj'M!ɀ0yi,qFz*ێЭ}-ցb xQ8{mF}F,~`_5d:$_msAo7tDW~= ys]͏z{fߦ@;9sïo{Yzu yѴ?:G.鑏W]6˛C(k?5?G,A?o? u6NU'zoᏄiʣ2W"~$WYgݿ<T2s6z<8qL)heFB bV *[JjXb;U# F2|{ +\:_[2xTW#mF1|BEk. ¶n*zk_[sfxaknP*9s@ "]Ȑ;'yۀI3Uo۔'vUkvEg$v5CIS@42VQoUi/ԩWQj"\t8 W-5pY[۶7yb(&&+]+2>j mIrz4MTf @^DDR+ IR1b##9=5`{$OUUvoVی7B>Ƹc?k '8k=GXnE\a=Y˺l5Oƶn2\ՏT׍vswUesָ>?&"?u cLeG%$뗳گkzX!H';TNJMȅ)/m'k{R`+rVO8tpp$u){e2b*jVXLV'R7CmK?zn7ӂ㏽1M=3~\FiAN{$2펹9!ܨށ"GgԱ$qX!RՊŋ+"I Tm$V(B75;9%N^ozqՙYB?"[~kJKB߷>ͼzfky'~2oY^^XUEB1 =T[=TT`eԨځÄ$D-cN:=Jo'> %S*Ajkll Nz0 Q?h$\ OA #Af(IX74e;Q9w$?b-ek GTFA$Ejc}7Ȏ nBr=AH52U8e gՠ_6X:Z\]Sapެq)qة*hdŠ&j]d3ލS[.ń(.z|bWۅ @ "B6vl,&3B՛U> ^R4OZ4 jB=P]{י}Jiez0./Ҳ<[%U!=D kA`Jе0 PЖLD f#DJ&k75~zu3ZZPm"Y5G+V- #WiŒ̯+AiǨk).6C޸I\T qQF+^,Eoasj^^T?頝P=QvёA (U]8(O&J`4VE'h+̤U~ո l+1(`EPj+lwuZ[=!rҰMKQ$:h 224`wmP͸1`l8=htk}r},\RߠIsxM\O4O.ZE Eoan=_ڌjI<< #b73\=*OJ.W؈T; dz-Ա]=fe4)mY`P nY"+jzjم[1ҷJaV G:-xn*`~kqVx.pL5!ovc0jEs'eT3pAdlNyFW b W4[L OY =f{Jm}hH?);z@)Z7b#L$ڮR+޶=h#Q+< ͣ[N7 -Nƕ}"h\7(V[vBBRE#r@A^ݵshTzm i3>qi& S"_Mv]뵧{W>>Ht7N<~I}5^)kU([+ҹ;ǚmŝџ5Mqt3 qW"mdߗ#q8~cC"']\j.d%dkr>Zfd>k޺jܽ~ /"u/\e qMyo#zLuwtdjA|AᬛU,NfFk%tnr"i$㝨n`@s]q!] N+W.dTn;]$]h`CiQLdHV{$`-?4cgC*UJ,`%뙬FI8m (ǪV<88gGJe]ѷ'Z7ѕ7G;18P@15ko3waI$w\7Ժa)$DxO~#{7YD׏3,ZOڹT:Qf .HJI@aޥ78uj(V7 qȬKfHE#hcs`24>k4jS Ap&(s($rdE;&(ȄѤ=+A&]Q%NhNf?I:c#z|Ac5e y*.8,2IGl+kcHH^XJC&s=j1`޷ MbSxJ(uv9=M%`MMT|+ D2Y'M,$ .m={T(KN{ ր;yKl1&3THvf-jW\\%+V=LG5a38 *gnD נUV3"f h\$ 2z%RE-nA?P(A:5iIduh% /Ո OI?ڌ0}і"YeRC1Ab͖7 $ނif~eY~GyԞY3U+jx[ @#=z[;c1U%L7VE Tbj[E[pqVkmnw ۦ,F$ɯ9}roibFI_;.(?W 1Pؖ#"Zt6ak鯥u^?nшIs=Ea+[q*u^֞iZ;~Z jOq/]kKf݂hFG5GN'HN++35kLdQ.;|d*lQzh{H5BiiPnP,N:PA-\%}= I*CZphTA⡩bjTXcurޱH'1LݺGc5TnwLՑߎ PtA+C˼T&*Li>=& =ՌZŒވ H{nDb[ZmnCne#ybhAP H*ˣ5e%:rLv5M:i˲#EUYT71 6C8OatUkpFwх 22)T=J1Rnن\I7sV*۸cg^MA v!TJ퐖́'JhoS5h,zQJW;LڡhuI&GGzN@of? g1CVk~>hh6ucލՋ䛃=~(jR95@IڀCSP -); P{wT?ɣ4tf!\`_;lWT5{I|9655VKօp]c҄1MuJ3|b昫 OXw{,vȨrD.#Ѕ<k[`M\3 Z3R[W&Tk{5N!]@\{Ո]kt(io1=B¾=!{PvwEoh-nfm/ܒzk>SF$"eOLwS=44wfOO5@v?4/ȜVFcN56z#4͒X)wհskZm`+ܾz)^qI1jTkq@ZfC(c#zjd`aO"Zmv9+]`cbfGq[H 1:PHCD" bLjE`)+K.\n{g5bWXoP":V#z$,`Oj7d+wIr3sFX ud;Ffd\dLQbx.GHQ _F?4(@z~Ã܏j Y!)'%|H<{iJ*K) Tݍ.)fkWw3n:0Gm0miR芧 ^e֛IZbes3ҭc_lZ%$(;,T(3AfX|qMȽy.1Z2?0(WrKOaF,;ClPٿ]yhWB[mRs64/ mH5Mj8'` anR`λ唒'E0V{p %aM$\X|dbp/j7tj͉CC$VVGat'xm= t70=j:us\螣A}D}E-1 rws362 ԉj=7u.1̎EtGbk˕-rgwv!'޽<}rڱpMvZ]m*=+^UrdqWGal6Y֋,mkB&Y^7mUȋU/\+{Wv-,ߊ"5Yja/3Wp?j*$qڷDքb( Oށ;ť`S%zb ~hſ,K~ELjkQSڥK-8I"LjV,)I'jGiUpvڼI i`'km$tM3Z>Xbקy~O=C®8W_o + WN~qֹ9_GbC@^ F rrQzD+*ߪ'RqmM @ߵd 'ځrT@5qR.02+cu+ǂDV"_ӑ`h6kpN#5$fo@į HۓQ,gg:&Z&OJ$Ҡ"Lvp=zᶑ5r2m}[OnIK\d ף۰0'5yÆ_U8<+tj-˧h ާ]2)G շU*[|Pvx]hwum(zwgH@֙{am]@≧6F7eYA= T>1ӑL[0A#k(3G5Pⵤm5LK 1ZBW(:YDTI"D 1792" f%ph 0ݪrbT$uqTؙ1jPӹXmڈEnO,6&3LZK"}K*K@#+ctm>*#CaZ+X.djkKmуSDL5ă8}JP_;OuV1^swOsY 8?jU yb2MJӪ+W&~ ^Np㡯'^\t=ϣtִ1"KW}O%BS7ՑE}CiدW{?TOھ?_O'_k1+%%Fֹ񣨿rܓ#E!iڡLe::)R#UNkջvz4nm+3њKd[9ӡ/%jvHsA&0b z b:1f˛t5gOfl nysAs`F .jY@'h8ފH; <ۥ\l'z02+44K3uz*a+eN eMs==u?s@[ r ~O7v`7Z$[Ml;W&'!ɏֵdbGZ)?yvBlW:q;Ž-$|RpO5,;y40VHը#s%t M<Z;P3oZ~+EKTH0jZ>MѹڅY;i8PX:h)=M*I#f8D͖hACmRB֊_P$f`8}~7ҊX@m( ocd5˄=+]l"V^oH c⍋5h$,bj\k6nOaF?Mq6"P@CEmax3\ut?k>vA;f+CT@$8W뭩昶GO\= E@~5 [J4 aFA ]=XJ A 12 :gY@U!ROH:K ZyV|m) My2_6Yz՝;[ԅʌ3QYW()uE!'h'ai OX*R!dPJ;(@^ PFq@vXhgY$e OLMT t ;!szq{lA<Ph_OX6 th>܏`[FС֣݆a1K$>F'?k1%anP lmE,ԝۮGAf 4 ͼ g6Ndbh9&@ @k%?4@'{(r=,F{Q Uz+w@cjW`Ae@T P*@twb;mk=]{O茑W#kםV?}iGOqTiC}3&+_S83aY`AVqj)xAcesg|$OG1W*}}TtA eO9Ҵtmֹk#[kM5ԛ1oGBrӸSg_gPT&ޯmqWW[u5R lVD`W*[24 3T.?D [lEʠID]MBZ#Pj+J8kZm2Ğ;tW}"Tӳ]{+UnT6L|YKl|l~sJH>lߎI:uWgOzOi-</k{,ĀfuX,mIDW C 5cՇ8-C?5D4T;EqEeQA6]uNLH[GЂlA'!i1jA$Xbg@h$9h"̳gނ,Ě(Ij檱McQO z-֠8> 0?OAX!1#jinrkmJ jۓAA<9fƷ2޽sC޷yt8bb:\gq#V("ͭ@vbdCMqnd|IM֕LvھPDO( .(S ;A&E;xM Zv3ՠm8R^#@w8(Iɪ(h3ⵉ-I*x>挦KH6©(=Q$tJܼ B{ւ"z^z -Zc ڄV4v#r"$byd5W! En-AnцÐfdT荫KlhmL,RjmX Ym5+zf+ND}*]!D Z65m5xkr59Qڴg T,좇g#=61DZ?qͻ7 W?q5(HzU>, MqD55Qb蘏k:o~oV&'tN~6Y62T}|Zٷ!Ifș^5]sA+X+cRLC޸2`b}l7(1ПH1A qqE$V'"C"}CފVyӮD@5˄ |?=[6ȬTnmĂ? vtaJ @ Q `jm*#t7j-{s*pH]CF[4VʹC[ ߩhֵye~~EylT9"u1AV{rn;px^g@I\rCu jwN$m''0e"DsFã!R3&[QxtV d H PGrzk*In84*57=>ͭ5eH{VQgIc& ޴zi"p8T[gW⭎/+ >*ǝugABԏIECu };l뺄m@@?N(QXDi\~Xل&bǜdyV@n]o4O~[cpPZȧ!57P;ٶ_ #s4MdJ֐Byŭ/fK0-ܶ3Fc{k16tvݸIG&b{O1Юew 7!IS[>ۮZ'כ"ѹH]Si?T+H k-"y$( Pm\ ?im!3j/=43FT,F1g0fjł7u;&heV($[$O&V[v??zTܮ%z*D]ٮPPNa'++(nSQ.`=iJ= 3FhBz3y mۃ<{\:{D^f1h쬢nxjʻ'T6D`Zӳ[BKb02A vA#L|笨T P*@)(DAmW\O< gJm?uk{yfivj.7%jj> QԸXګ;zIuv RތڮD޼J{ijzwe׊XȆA݄*W(Vu~ݴp ٩\gݴɩ)"uj^ f1ѱUFOqE)jXH?j Wme*r"FDzC_mL>:Qiӽ+UT"\C[@ XhP7STFң&;X QI"3b'Jڥ/db`'^^ʂ.Đ ugĐ[vN'uα_˶h8;Ts_?|ߧf/~[X!ZTLUFj߇t h^ar!8ٹb !"'\h׮b#)w`|:ZZ=ul 5H3 @vxMo`Ey&?Xkqsczc!V&AlU1’&kDAa1ցOڂJ@y{Jn1GZ2&HGf`DjVGN;AjVt`KX-iT2JfviXU&j,%T Qk Lo'jC$JmLeV> f8W9zYk@ݓ/ںc+uf#O޾?{?o1@7NGC{cQqYw8桦 wZ 95 3kZ4ۆIt< (Y<4Kc"Dzsց0sPɸ |+f("ǵYHAz %W' [=$̊߶D ёѩ3DSVm>jLA\gv4 QBq p055fp3MA+y2'SBrz`#h$8uHCj@cLWltD e rQHހlmHDI`o>cFUYն=RS껙jؔ]6I fv%n@$asz#WRQvXDTXQz"71*GfiwfqCI@A4Qy M;D<޵{`'ߊ"GR5FԽƺD`˗ؽ;swkC% :u5lnR=C߿VAVEmY%q'yf^FӘ_RNJcbFcڹƗiԲ-$"OXO?I-.;Ȃ0+_gv-h2F'q=ToYvvg$#&9yx\R&G⾟8OIs+ծ,ץ?t=s5ļMH2dXkn(ȿN?eAN+"ҴCXMsVŁh5y3YƝK:T [w3 qߚjTN" |P[VB$֍fYb}Q֩8W4O=('P -mI#4B\(KIR%m "hoXsnւè@[G#P=L󺀷M<fUı'1FU=UߧX%foIbzvT3psUk{R=?5Zq7O?\ QGp.5Q]38$qX]BQ n&GW(QD6'Y%q&ky@saFj?%MmdЮ[`QI!Nve􎧨k`"zI@Ib@kuWJ޴ *vǼ@+YA4N)ݾdcu;Ѩ]Q fT`LզZ#3z|D+K{=^mpmf۳rćaęJOL+}:FUy0't GG@+?||W:oԭVkZw F?zU0c6!q=Uz?Q"W:e>jж:n@,fGZ=tnƔ f6:PxhTXfA U`D4p[h1C4#uBւ#R2 Y֘AsnNh"6@]-Up!cp< $cdlI5Zd:d)z?4i2)MG"EHX+e@T P*@5le@MQ?srŽMq<ߪknptעr^%eə8Zu9n{*i kRI0`'=)-Eu`+dS>.j,h.$7 >ޒ+h5Wh\I 0++c;RBd.+_O1s ẹp̾ŜMkL}Dzk=y"|Lm.[G(W:qhjwNݤF V+ez8 i)m1F7 zBXȨZ# #w_P6?b~u!OZ>.R&dLi5k45ww'|b Sb} m8Wy=_ӧڳvϥ(}Tu(g]j#[ZB0bvdh^ m ]Qwֲj?52T316Ͼk-y&$f+<ʫU5ImIJ0-$ -WQt:L=:V CH12 Nx։8(RAFѩNYIn!'nz0lC䛍_IY&t +4 \M0an XŲPPR/j$|V({Cn4jt(G=jTMl[uhn\c dkk_f ͧב^߉7ԁbeܱ&W]Yz oE]ۗ^t|^sy𽑒ȞYg<|#s*cH *P2QINOQڀcj!z D$5Iw=($.zױ.ʠ,٬DQzt  ɠ" ʡ Ƃ6A3%\Q"nA2;9OT(ILV[wJJk4>L*yBťf5a,i&Aη!--8OTZȼ v9R[j&h {VVp03J•90RL~?V2m͂?5hЂ}=?v;ѡ$1=k*{W95"!p =MP -ځK1eb-։6#qMKl /"nCZ `=8YⵔfSީ(oP#S5a}C4``ɎG5` d{#gx2 \H,Ϭ~kA(&7޺FUA6+ɏ)hZS2ݪ\AEG?7ƭ`QL8;_[[nWF 띋<6(<D`lOaާ[dtG4'م(ڢAe']s#61әdk񟊤.- mݫՎ٬*@䘩Jm>"I[.ZB6Ic)=lDGC[!^1?sTR,$GaIo3'j/DEiT}#< d}3pyhD]{5za NgM:-s'Ӄ$xj)+ŎvN(2\;Hdd5%28j]6dh[YYA}:)J(kV,49^&Mې{u2D" :M8T47*o4vep!bQ:=@b'i:+im`ax[UFw(0UK8Wr:+#X:GN 2 E('T[wdnb{H\3hNg*TW@"(3(FUډIp@t@A4R2;6;+ZӍvHAcV4]*TG0KRqy¡@P0s yQG4lAvz5;k'rLVĬ[x1θ-[*EyZ0YLFfk X ^#@\UI@#9Ȉ$S: P#|2;dV`]kT3fd` 3`M0D*$qi% jT51%&wwa p頍)?I&ڰ 9)A>9"PX%95n$ LQ.w)4̍tzE]A$ 3C0ѠزKr\S,]my ={{GAs@2c4,EL(F勗dh-N>֗n܆$r+uB'<̺[h$ڰMނT P**jD0VK|B߇/p kWXb'#=biElg5Ţf8V]iMPm A8?k,ZFG憨\#[E]H"jm{OX(Y`gh}n4R,1q-:TՃr*zXyG~k N݅kztGvơbW֥in6 99Ud/d_Q3?VX%P Ng5:UN &9Z7~X@K]Eqފ@WYڲ9XP77"z4K Ȭw:ց<*2ނ L@ OۭdeOi=fL  03 64 H޲PV<9P%xi&+" Ͻ$楺6JI s'ZnY2&yHwY5)[ָ]t>堶v Ev5ضzDgRcSuJ H" # ظ9{sP&nѤo1hĵ +13A4s@Ef7yV ˓։G%ʌT#;Eh="I&hd.yn@sWX*s]G$)%ОY$]#,E-0(58vR32y1*`x]FNi\ Tmk"x"̓v*^E~A$LzU{=~[Wϴzi|8[j9zV>+id #z\oj\xG!zc0z s{9* TenHUF(ߺ\wX<Uq8P}Ii7.DښͽdѠ,vø1XM!2`G5W8-oSj慵9 2MI2؏NRXm#  n뾦I3蔯P0|LD7*Bd Tq偶9~mHpBL&g@T`(Q.`&f0Ms4 ,$4ZJPAe ه0~ ؆YhmHxgHdmbas@K#j4A= J kj>V+npzPϠwZăh=GNmDYn`qY+V,N<("{ kvlncUVy̩R4K\x>W]# Vȝv_Ih5=GtwnիVrjt+@lH k^)9To؝vHw"@&`{WH3|+0d-@U 2IDcKpLw!DL~mt4|(Qu?,YsE!v]L"Od#({ݱX8KX_bs|և\k#mOUh[6WKdkqKmd^*OqcZm*ki9T{HO5zy嚷Mt\mu=gO⹶,Zv 1RYє]=JKn$S/#mu Ȧ]ɑԚ7ތPy!Ǟz+D?4-a{ C-9"qPY$Afmn$SA9VA؊%SCt3X&P##{86PQn#ompsuV++@M`6ڀ: m-''-i4\hF*J=kpWp@07vkJ/F~}E&2\õ%t&8#F7]8Z0?ach_=بT Q:Ta$Fޙ \pɮwr5$Ni.[n'Lf;ӚfՊ#&`\fސ <֡~jFOL]L}qmG&)\Q|l`O[b'JٌP{8.;n\@LT+-b8ZLc?Sc5!F56={$˧&1NPV$u5^Νnhn8h$Z@{VbabM.m\0du`f1.z[ZdԮ|M@3+t69^^zmxo6޸6dp>Ƈn[:e}C_ԢŢ7zϧ %ݻ1pޫŝ<hbrA֌LC w!sqɐrk=a f=#25l2exƜ1 iڙ5`ʲTJ_U$tVkp`sY'l8tqu5pjӭaZEAjrOJ\#ЮO" In1?+|9Oռ%쮞,!g5>}I\!d0ʬr)DfejI,Ap38*@ ʒsm%f[* p=hʳjז4nhZL.@<Yb憧uclp;DIA ;) pwN+Di$J '4eDkxlуں'lT<őީ{uZ%e!=XTn92}/-:zlJݴک4&.JYdTŔC}ڤ `8հ7a7zzO5h ؅/DkjAƞ#ZD/Q9Z+0[Rl=qTQgVQ,Z6n=jMG9o*Hˆ兩#O?<};M\aqϥWm p,n n[%rXdjWM{n5ݶC)枭ǝhpXzָO @UIz1u4z֨9 OPM8RrjwP6?V COuBzhK#z1k(c+=R6/1A@erw⅘ QDq='i2Oi{d0:+^QX5n# 7~(Ӗ&>(dѱp=hH+p;0U"c|PÒכfgQj;+ 'a'Z,9z{ -=*#{L޶2h|U%-=S#qa*7hFj`QؾSDk(c'bhm BiQn+0qު0K=&:V,dI.L14h{;1"l;~z])rܩҁ A?N(";cۚ ܸ0_g,qۣDd`~ @?N b{TW'V iP*HNO$s["lY֥ ٌw:D`[ m \tezw]^(RGJvlI XYՂ.b(ڀX#NRoS%$L{ 5+z@AQ(:( Pl|[f'UG:&6s In4Gz_ukec'J)^!Vr??4k\ SRmLsY=p?j)^Qv`t2Gۥ| F [ !E $G[ۓ<⌃+f59*.ѩ"B LuS+<F=˛LBA+$A=+[`"8={NXFj=3UZbiH{US8DF"~? ]-oWx8ۨ"hw)v׫%f,AN ?FeĒ& $Eyo6;<-'kiv A慫#O$ wl>yAQddssm@ RpoH@ĺ@UvMLJ[-Ihk}0?=f p~ǥ4N7,n[iݑC/[!O".wH#C(V@J뮛%-nPBّ0L1A$Q3l#1ڭ@D3DupOJL~t6EַJ5Sqm$ \g*կ޾cP*@LxeF(4E^3M>Zwsˏ=떺+; sǛ._C1ںz9{3\3L=o$z50&WwUWSuvDPd^QuFc<[6oFjʐ z2/7ihd_'=jYwauhZM܇T՘ˌ 1X &r)z8&U=Ǹ[h?j7R3 V3Y. DZU}}{HT5Y%GV+U!c೸3'QTCT$`VVO@VdR3^QCvi͢3ظ%an9187>ՖV&c=|W^ᖭ謮 <ג4}CYmY/kאcڷ蛻@}o?_z*Ͷl);W|NFokYlxHP[&XDt>K|R$[0!*'q E e~Wsq)RZڒfbDg3Ҵ5p*DbdcvQH95}X@ lӚkQicX{UX⁂xr*`ps#`P f("(" "B#Y0{@zQ"#a8爪N Xn8 QuZ qwwV랹?ڱNV.9J(*`b;\kiɐFfqE ՎA3Kqb۽ F%I<z5hnq4pEQ`rL_s59↧br{TeVKM=J&B71L}LAOjq1?[*zkey 5 h)_5LE*duEnu\OP>hC!ZxyvR>5d%xLGZ$/ LDusU@;Xw2&cQA*[S8H UD g.K"v F'T@j owXA;ZM8#'DvYmtQKL[Y$,)S@B-[׵e0{MJ;T0Ojq$5K.Iȭa8.VTЀf,sDVVs[U|=*j.i;y`{N@K0sC]?ތ2-Dh.+?kYjۤq3TjV^&\ I$UX~̈́)Xu[ iڐ\5D4{O*u/6d'++ubւR䏉ҵ!aRg O6:bSҌUfN}å$S׊\%IL v[?hƸ`ڨEs@42i,ޡjH`vp;߹`F͉'ݸIdf&עHPKc# }Ic")RhaډxZm}@{k|4&6ٴ-/9a1o>1zo7BLYZy}d%!LZ~ՔdrlXuFWQ`9sNoL֛H_BCIj0m -XpMPJL0+Թ₻BHhA6_ }K%E\䞽(h ̿4e6*IMa 7=M"'l"RpnXmf-Y!Qɉk ݽ O4n7jz6yiq{' 3rHڌVUb,!^P$]O Q8/`xEm;r"`f-ט`HJN,)5 l''ws]dDCGdW}oA 9z_|ǤTB$Hbh}F֔K_nwqQUp)hl^s]Ǯy2X4~kq){؍k*jjkE`$-n:p"}}f/`PW7AZ3A[$wCjRO5PfXd}{WIywGNB4(OJ e$Hr::8 @J("aFjW=_5*~Xb\jwGlX+urZiY:p2229/?0)( m ^: 7PW1W58U~"Pp= MWz0jj [Np?Er[xZB^U%OXǵxO|'t#gEpW%uFrU9襧;uVߟ|K>VΡH}Q:3n! T^_G3r e(U_ΣuuXs\Ojiw}λfPB\UQ2 4Oث3ULyYOctm 2OJx:>|jR(a>mznP܀w xU1%G>׮H?m5kz@-k>Nsy7}4qmJd+Ǘ_?9a`Evf |W{FZA^՞̰Dkq+YkF(iFL7LK)$c5fޝPdm'8r 65lqڄ Ξop bvԌdс]k  zֈ4f'GӺ=h{,ъZh'A3Fk/W)rIb+3Pr&صqEhe3z3/_WHqS~[v &=뇗ә!n&lj(fw ̎Xг9tTE8$VECYVc  `#0hUH=jC"(i(12{QAԇ w9TeD4?Zõͧv#JG!e[Q< d$f6!Q9W^j 8QՂvmIlPͼ<тbzVkRYy|ԇE ??k?]íK=(&MOcPh3= ǔnH+V/X3ީX6 0+WX\ ǭlf'J6G8Z²y1kem*[ݖjue& 1LxJQ@ }D.#T(¨BsJEU[,ܸ&{ f];dOE`reDԭۺU5l3Y.+X!lhv 6znџ Qq88(MsTPl[qjus1P\K6H4mf&ͲB(3ԈV3THڥFhHYZ)|Zy Q@՜O;Q즠zq/*RuTeIsډЮͧ,3>+T%k`m阩b1GwpAS[rql6n@-M03ްFw̞?W43(.ZLDԱtc>F>L[Pdnv_"l[8P`DEu8K[f~s/0G?o xԾ qFdA2f8ǞxAp**I{bZthzԝ{_W~Y. JjCs44]K-Cg`I'UI9&Ft]sZVcЙ60㡬=m)qJ@Nx".PFWbXEuVhU#zo=;h ^r vtN搧q^m[f(z־z<oH.1xCɷr Z9x>vO1uӤ&=kTpnҸWYFh 0Ebܰnf5a!JVK9L{5U2J]bؙ I.&Jޙ++mj [,%Rh ku IXQeH@ojhyPAL'>Wr$+,7SiĩV^栅;QNA"aG !v&*Z.e4fjzщI_jvmf 5Y7̐xܺd5X|[P&9Tay`I\O('[AAл`?zĈd9lDebLt&ھ[TfTUI5bV>E8U9>~80><+>3߽t>rYZ z$yrdMtjSJlW9= LH?zRM0c_bնET̊[d{ay  _ KK>W"bwAӨ]ђht4uyA c)T<ⵉGp⡢ނ&_2D G?k"+HOS[ٹzS Z(4X7䎴nue@;j`-wZDD*wf 8zT)Zuh{tl lI'ҏ1H 5roOR}+z/ޛCe7X9E/Cr͹T886:G=b.7Z{cmH#\tx5 b6 pS3>mO>1|[˻prcN:<#UwlmXf1h|STnH,yZ0s1TnHmMJaKq$oP^,r y|k3F"$'"u^N4U pMq庺ҙ C # ȷw׵@mx?&^wBpzO?=r("; Ȧʋl ʠe ԟKn[ɪMnzMdzpǁM ,(;]! gVMVA#ҳQOR0URSY)2eD=VL[ F( [(mg m;xNEݘ ?Lk"歈Oni0Kwcc>iv8a=92zb3WyOToz ZIsҼk者ͽu-(dމMdۥleI=L@cWE+&dp(8rn>*q{W?c`n71+1 =>b@@ ='zYLĩLP0lEԃL+v,9j*B3)=*VlM,`>Bɽ;Ne=[-58$mp7=SL ms#i9U(܅[+h]eMjZ Z_-'3U8%Vwliuv,W>å:ܶ'>/a[ӪdNp+z + gYW+zEst1띋6N*9fs1Z}*31V$qM:i?Pͱ}ꚛn Ğ4eETf9B'a !?֊Eڦ5Jcu;6N}+G *(l(LzV[jSDUWKB +#A  @q*%jf2Kv4|$JgLm3ҷAMC\ >ޚ \c#)ОXu5T߻tb8x<}AOZ %'+e-VwZqk.+#:ufP]BD`V’HDeNUِ3zYRҹV7!B~&J9oj&ra hn gJXFe 9.?'޴՛~]øfIզ.EajýZG=GPUfF @,J )DI?5Ynmv'?ozJV2-Sl01GHҵF#i+ZXQQu%Xz`hہ~ՔU0x8`XS#zbfzL֧MPC*aOCQ[oX<3OzeWh$%#  ʆ} ȸ`4HKfOz뵹740@ Ziڕ`.,DQPԹ.':c}#?jv޲2UmjqgvU8i m 'ZQRX֥NQ_P&`Uj0@f d+'Mut)=-Z>A?EB*]'ޱ8smTB9SaZ OAڂ˓tH A#MjսE@[%tC`um4=yǞ0Eynʟֆ䙜Dc+˙MWb ʕ"tȦ_̴76y^%jظ\d\Z6Z M@僙ؠ ju`.ܷu\MO$f zA i(,%I4 :.#1"F2#8榉uf-TO5ߞ^nq%-Qf8]$sV c3V]9UO:zf1Ll޼ňҘSjatYvTحVt5S{P4 *sFjk?ZuO\@cc%I˧GIM5떉B:U#]ǟ$XxjAC˺S1#tkpdU#Oo^CrD5XhvD ?4kAx'+l4D2Y{ |@[ ;k1ָ$=ӯ3y*ԅ;#mS:dUT5w Ypk0{YxYЮxPybk}KZ䓚ht7CҷbNU<3~W|"k '[`zxǎ?ԛLX2Fs_3@ҥ3w簮uD[$%T9Iڤr;Ѳw Ϸt0=(`:7LScgY-?4~P:~֦80I&&јfXk1T8(ʨp b'N= h!'p&MB(ClbVT@Wh@]Vm(<9r|ƞ+snvwb5YVH#9'R0Cs=oQ=~+u%Xz+դn1Kb")$Q0s ( ~ Bbzkh-+LJ LeAiDl9Ns[ AMRHsT -'!; R{A=B=ح;RqFUAq$P2gz;{P1,v4 *`@7gs }c(V]akՠr Uev fkLTf e %0\kVʅfd[Wl;l?ȖT'@(Zջ7ghEvSpv8#\  O4DJ59?5 +٘kE7<1Z%%XG5U_=IoplΤ(yFL UV+q>*uv= ɸ jԅӱU&FZƞe)qH` sОZE`$wb`˭bJÒv^3[樕-s1f͔lfcF5yq4b2>^nKy dMͱeXa4hl2AlVc1-%EeagEkA3ׯhT\bEf!9L=銇PTaph֓h t ՠO3lFpp( ^r ֲWWi+iRp?5*}C9ZՄAPU\}3=nڴL}ULPYT3.Ȟj*jm ?]xVtf~κֻx%zֺ^/om |&3һ9V݈sh׉}ymEq"Q;wur`O=[uy%MEtHZv0F:V(K|ATtpH)`דQp޿;"b3h#uhgm4j<};n4yo$悽 4/'튡\T0F6M#'Box m(GyYŲύ$xzV3}0LwHײCVjbOZi6NR$qkkԚضDW=j͝ ¹_JY@E(`w3:/xmPh粆5)k4m)}H~(%0$c&3YL8?zvODy5%b&LPkv.i;89WX~h#Vڪxj58P 5kb{ .DB局0Ԧ(h s Qo̴P@=+`-ZbX4mchFӫ w*Wm0 FAҪ'I\Z]b15E\`\n;{Vfy5*%Ra#PV? M h Q^QɨW'@6RG?gÿ~z5R\N-k^b]fbI$'ڲ|K^o[?}>k>VsǽTI@ *>j =܋`ERTKjqPڡƩj&3?$kwJZoaO>>)\6{[\u¿^4UX"p8=;W>_}OI%g⽜^Nˮ7S-f*}.”334e"Q휟zS [6o) k9=`mCqZSIEjUouhKF9TXc迦)RЀL zlHs~sɯ7!b-Oïm Jm7Ysn!]DüIkSk| f.;TͳКfu-(,ň뉬d'ַ.s- Ibui5.߆)w {Pիz!#ԗ\NZ0]s7}D/0 ߌWyqBձ\vˀUW4nYn.ykCi0*VW#DS`AWD*-Q10%3]=`ip4BZ0K+Њ7fGsC{fu0 +CBN} p;vA ޚb d~x܂ʹӭlJA*ܸg浱gMsvvv)wSU60SO_7D{̒Npc04@'eW&F͵Dg.Hr}`&᳝ⵕ%iwQ!K&$m%6m#km[_rj⵭_r$[Oko,h׷W(n dvЗԩTP6,iY* rI,j |O" vbqڮ䑎ݺ"RxIh޴/im[J4M5 qBu+oQd6`HĐRqލYg&ր,CAXڵmjiiIcbaPtqPQWU.4@3YMFZN.Z6 z6<jsO%\f=0r+s{]].[Ī~{}JtoĐ$N?n>nUv T*67X+ڡl[a A*"^² Q fMcMso :R ӋNI9=~fvo])f~=Ӗ!ȑuX$?yDb&'@GKKqI03ނ/v jmSeUh{%UlY3Z cn2=ӎ(n-? @z|^6{V캪;KlRfjݴ;t^\XqIQ@?ܱӎjPG{VͣaJpujh Ojʫcԋhsi]-"*@v+d 1$<܂ `pYRfĂ; B N~8(jVmE9ڀ-}nmT?R.ZAT]Yo ?yaަ]apZa]o4Drk+CҫRU7;Ih[F1P:8۴0=EX%)њtUc8TghA QZ>ژ^,YXts&+M;;ط. fԐpM[GKh. @dEa;mmA;39: ٸ.X51e&!|W9ӆߨn_c.Olی1ת}=EGZ -zާ Qj5.$c%;ZAh5.ɢ)(#hNzgv!;Jy q`ez[vlqX?jK]Tg>Զ eTEOiCKI8xEel9k#]"е54-։RaA>kW%}EbK/1^>W=΂@n&G|_G_zoںPՊ9ھ7|]*3xscZ:}A{p扢սH%wɣ@T&8*D[+ZCAʥqTI0OxL)ݧ8+Hx9"qںx}XD(`O?5G3ƭ7]X.2q15Z QDk+v!aj IBpɭa4-e њ0+G Li &oz4I)IBޑۼ`@[\hi.ʂ'T.2DR=̚3&nzzcX3jN2>*jsjJ0G&w)fm `zulNHkbӚn0zzHf>7ʿoQR~E}ZN5>K'줵k$p+u<)Cwp\묌JqTH`0r*TfrP67 R |T~+p:1+ng %/ $vV$90}GF dC A %RJ{E&fCc3dbᶬJQIޝvA PKxҁ$OMA(-%T`ۚ4A'fT ÜW"jՋGvbDBHQ"}\ÕU2Ev-[icjAet l3*`_b:Dr:\wqq:U.SC!%ݰx5DozQU mΧf;R |Z ?4Uu I4feÒuV`B@-Qgc @URmn8&ݿ?'7 Sn.,瘣;;A N  %^(ŶGJ3*59P VrOZdC-;zM\MG,QBj kHMS*ɹ@vD1b$4 ʰ?l31 @BAAnۛM T qV(O [̠'5qe-O1U6B:UF%碢%@rūW-Cx IW:5fڒ?\n*zJ_/ƷV[q;3R ŁO[.A jQǖgZm 5A$b.a"OIcMa ^%k# -N;:OZ{N7ǘ@Vub8VUp> b4A M6Ika( j[Z7VP6 !zZ!gє2w#%*@bx4 (2yo$Wj o H,Ҁ֑:֥clɢu%m33z1b֞}' ш/^dچ&#`Ѣ;1b t@kd蛧%*IQk68&<'k+Xۅ'u\+Z$LgF+=ݣecglA=B*RnTlp#Zv:]2Ȯ&Cg_R6zq̓ߗ7\]ZgO;goXݵUpsUsccY"]1J-l_k*@+NZA %DcϾ8l-.-`}\h]1lb=iatn1-_ڂ@0Ah(޼T6GZ(@>IAL e5(]i*y`$xqj6 q3޾;{QLT p4^2n1hIh0>]9*߶R`zBѨc\\6˷6PaՉ,zVql&.'gI5Qj4eʖV+-aOZ5^'p+(M@h^Kw;H^Cߞ L/4TUfOC-drZ**cs-.Ԑyp+,RJ-?_7|x?ޮױ|5r[ebzߧ<_k^4kkzr>ޙ5˾]^^ͫ~O%{OqnZ'BH<ھU| }ӛfk|{DifwPAeNbҲ OZ+T4e2sbՋ. <{Gzƽ/3tɩvڳyĩFSkO? ZLx+@]H=y]7|ߎe-Y*.ј/}_v[o;!DOl>{Wc=m;bf{Wf\z!Tm2MtB hds։KJ(AF{(Oh=:FIsL3j@h%歔2#RER6'C\ V*;hҸޝRm: &AZkq!+0 Lt4m{'Mvƞ-t< O<:UW2s_gϷ= mS8?9 y_[$!mM}`Fk=o\;O^XQ (1c0b:{P:1)",e;FqXF`׵LȣaH4iwh H`ՠw+GsIMf{R`8IGZ %ILe;5j;f"J6FMn% X'LA"\` fծ&ȃYٙqV-J=T+H?5X!k{61?C{SU[I5|SPBOŨW.9~Vc\]CT3 I9HAEGqX`lwc⭘D)x*wBqhIbSP' Q@֣c߁($[V]9&d3je-?hYypᘃJ+{pQl,171;O^ڀomUv#P Y&~ߚڻq[ 91aشs,\eIvA~(Qc>&Ae`0y$H0kAlؔ,Ǟ*SŅ,2'M[}\qM-7  >mRq'%@l n˱l?h֮ϵ-QK8U95&=ZE7a[ zF%`CK7.5XQ`x[Lݹ,Hw qu=DHYVu| Q{ p+*4n)93>E(ݎ@He)$Ns4j{}9:igT,[H=drӲ#޳"#3{ 'c[R" TGV7U0" 0ۖݰ&Ci713lEh3Fõ'8nB@,r}A4ӕdh#QDY_(D2:Ozءm۸ ,@tEbq;6j8H0KQ5&1% 1VFn` 0a l< 5BN<qZ* sT/4u^V-& ; DB?+0v7$b>i 0:-[dP`ϰRȒXYRq(㼱ܣ?r9KqO Sk I&P V򌙎 SU[bh(6Tb-14.}Rf>*4ŭq! 92崱"@TnhΘul&G%j;{)dvqN腌1+827,0jC50m~rT8֦F_j W9Qti3_O=L#_B+ǵi?qךE}`)=YnEs65x(C=k c-\MNg35r9v$XkS;I95k(7U@&(BbIQ3榀a~UXZkYO[<3T3ҹ(C 1DYچfEXz'\"DJ5[QenRH=joU ]I V(j!Z@*iUmkcV/j7zWQm}6l:&xڴIԢS{3j#^{A$l.1g ( E`u3Un`Iv5:7DK䑸Jݮ qRޓm! &pj5q3`]sLSn75V\W'OwzzO lL91-^,|}JdC|T,+7>.hvꋉQ9'Xq, Eq$#$I޺5to*9k/[%ăTNĔֵ:pNRښN~Ee:}Ꮸq\zH2@u_`%cMvūݵxO> -?rZQ^nIӋׂx׈ -3jϑ~4dc2xߙ<?j]FbUc] RbYDsMI0$L]bhUhk3V)C3A<(LaUUH; EA, HeYRPLsޥTn6Lzʲ Ji`CNbө 5k@mGjڐY'Sn=IeJĶǶ"f ނZFVs]"ݸq5[Kps-4w8Sr>NlQ5vpUL91U(P۳v#pe:l{ډ@ 33 6`C L'ɠi@QˎONޛ71#<4 :uK^cH''UHĀ8R;vag9$WHʵэS(/'5-{ZeKw^ߪzūbVkI9xmԿ.q5kHe_oc0My|Tq<_WkۉuuɮzD—k0#P kR %b*$|MsEӋCȟF,^܎[ښ)#n2Ysx(#o"=iEt\3@f_* P(]9Wm$x!LVi B LDNmzqJ<@lw54 4pFg,ܩ=MC4EpuP7y;Ab~hɼD vH56Me E#ӳj6n'҂M!WZ5 p9&LN={0P"H` j2+Ah0= Z2!PN>I,8 Z]ްYMn&A?K5s^-?]15NF~x6ku O2)+rQPj4b)BbTW.`޲H5$+IokUiV0=4U_"+ݸIڰg\ (kRێ3VĮ}DMM7G模\mDsMkb2$ C|RDuP;p~YעE wNB6XOZ;Ҩc=y6n^RPA@H]N5tn>;AraED/֥Sų榩fޕ%5\TOO׼F I|?̼>#LeH}]Wyw~[=t?z8v.c|~*,G}|ψ|Cĵ:Uv޿CO|o7+ϵLZ9޽˸\M7[BK,>r%U݁U; o ;08Js% 30PLvZߣv\MB{ 25?Ik˧4w$Sf ]xZBC \޳{\՘BH~zqOQğ{YtpO(r~O1S|_NݸT[+i)sbUZ $xXۛ#Vm 5@|/jRh X6cj5^>&⭈KrMn:>ikzS;LVb}P*V4!ݐ(Do(d4jx<@dMHr 4kKdQw;6ZKMhh=Z[) &gk_zݰn\#hkoc"1ݸo[J;X1czݷK0drDj]"d+֧]`[" $|Vɥ@9 7(k*y%SB$6:5"+?~S ށٔ΂r" #2' g ւh@2DX3ɊRAVhd%"%opbXYW$AqZ qQ81`HkN1]"d|@FSdS2$=knv Fjna(/qSkNC>+uL?4P@CskD(X@-00;z3R!퍧{Nȭ6˴4m^f V7zhap$L.NsV 6ǨP+ܹĎ{J=$ʱgҥiⵃ `[XHl@5QRn81,h"G PHܕڲH =*WOM/-·^j) -2-I*pG2y A ݨN[$HM)֊uEI 0>`rpXLh-i6&*܀q$EVj݇q_jkDoIYJ51W蘱-tTo󕶱ٿM uW˜ 5Hb:yW;bs޲qPllcQ@*P${P+V@0I.%g -%=+(Wtn9RkAP zXj 8-w~h,4f X@mޓf{b{`ϕE>4[ ˽K M0Cpʸ1DY-ۂ5$ I4 tI;@my8 J8}mFv,e[Rbx*LĖ_on %"2O8"tPDҹ7Sc1B"5 p.㴙 |Q.ݧMm@hG j㿤5HQ]4{H騐Ł{Phm1ւv.'7$1ta6sSjSt`@=B gܼw\m5%f+7'*RQAoOKYeTf~CAތbߤP4s*V$h 2ēZ 7\bDcl'-%B BYcEsn'@y[o m~kw_=֘3%AVWEѢ0hQn\ޓl#\ z!q}JV<=r\ɀ@Sdj;s"kyZxu@~kɌ1\ڃQLUƸޕ [齁qZo1ނ!&7 el7^o: v|V)hF+bjU77nB-Y=vݢTϨMVo[ @9#:KkMݿ0%@3]'#ѱ[v4r7)E2o3rHɹ}bo@$ވ Q`1dj7H9V᠗Pvzx{U#| B ژu-?57NGJʰTshxW:4; w l=q+Paڶ1wN[]y?(oRF6+uܕ  UV+Z) gAwQ7s# -M W.:lgj-a:k1kIw3\YyEWDlk>O5OwUz *k_&[-~s^T/|K1{b*v:O=P>'-&] Fmڋ+kYmK.&x[~X ?Rc2tPmVCt]<(MP<_Æ[=[+<ޘ2;2Upp;x1TXɭM H0{1uaA .4ҚبښR$+Pf→? 3]|PYqF̾Y$I( Nzԉ@ZuY4a8Yq '؎Ak5{B^'(kؾ:{{p>+|O|Bb%cWגon o4ҾwWuuQQ;R;{%0=#,g |P#J#u H3R\3Ͻb b#e#h8i0jdWT h>I(rr+AhŰXΛmm8jm Vh 6uE DX=MĠĎ+}TxcdM`Jz L:EtX޺cL&AJiwl Q'7NkSDd.8W]o]`gqNuhJr1&_.C&pۘɸy=:ж;0,Kbh|B$QfvEF $Ds ApP;j<(U\I$z ިH16#=lAԒ=D P5蒹ac%z7KQ>L]AE^qy weiŢX:%t6KꞜQP$Vh 0;VV,?Zh&x U0B:r>nնNL[ ͵@n:V]-So,bzPBߙ0:P1?n*#; ڀ-lOL=4AyUzװyf6հ@C>*:m+ @1q5z. ,V因楱ST8\] 35;FKAh&apJ Tsx۝:L^ n>ձ\SjݫHe@ 洮Md\8a!jm[KA2k(z&({p;Whm~d$C3ǹ_Xxnz1RC ݷcprF1|=kQ{THSCrE0!( H͹IB[wGVR"˛d ?Q@瑌s5}%J8aRy@#}y|bj!0m;I[=sm&1q64<" %5^{,ZHZ.}dڕ0 zWmrkg"zEM',}^"C:\:KYYjϩWgO3q_+mTs!L3\5{L_EūdOcMvQ,H@uo˲ђ9 헬13EڍPW*A1iZ ey65sH3ⱸxc3=FלWx3`nѶ1ލWe%P=?U3ڃ=A l RO,䤩c c3E,k@5PyThՍ1 Xd:8QO^pUpjXWD,( hfbk@B7 CPjAΞqr~iM!J{qXn^ݨ ÜRGl4oI&1 vZc8cP~jAaQ@ڤGkgzjmL/QqH&+tU{s [XBVUb95* >Y%}YT57ny01D>(/iXAZfiK;0ȩƲJsLe\7ScH m3 Ro7Q,Vmn꣧[]-h*m{dXz`N[, bkF}ArjMY&mzLTUѪy/,O Our?ҀjAa*}ZzòieOjo%ԁArLhQqqŁYWnf)5m's$ktJCJǩ{MeԴ7.^M}5,O[|޾WW>7+Iw=kᶽd~kr{|s 7i#@ DҾVx{h8S%1Qoh s&=ШaGXZwR\H۔3n$ "xV zU`pgXly Il=hj5X辛{Qu|7O ;UMNlulDl9qOxK/ʉfsS5qqc V=jm;aFVWYsR=cQvO|BYHک ŵKz˽o]y`=*?ƼQGVń('?"6s2GqDjE 0 [V)h&@_Q=(2vyU ֦ MR @zRkj#2=`J25{CJJD( a>?"ÿO?^nF+o9@BdI&׹1¼=GW=V3\k5AKjU(lfgh &`sZRWU_Iڲ?3hAY{B*`dwlg4e +cj%< 5Rϸb&WXR-Mcaד-ðc;g&򫁟jF%є3"vb@9eK.ǽd Xt Ҫ V.9AU+\$ 8kb &@=+QGA$ca:ڽb""Aq^q.$$@'hrޒrA5L1 ޜebޅoO#\]t$rnQWa;{R4**$F}D[JϨf׊?(PH3v+&:w 0-~+@J$=-"u=jśj"An0pnQ `5y@MĹͫn2?kPvlњ0x(Ris áPT L\qorjw`eA*Ph̽ -2{wvڄQ5I1$H!jAgA6Fs w m9PK5I-'Ə7@ORkHr@\W4ۚd`Իc`[l+^1|B +h$W Z 05ņNGsP &rhN u4K4x%z"cלPWȐT {`{W0t$+tX 45p-y58CqLs1Z50qXjveb<H[j F#3AGPdfwѵ1.`4b%A-:R\G`f7QrvC5`-` lZ4KLO P5˄mDbk7qzp=Av(»Mm];@c#ڀA>P+dh ;Xs(-۶y8*D#wV.*6OCAE=ی95`[Kڈʞ ˲0?L<6KuelϨdH-{c`ncS_ty:Exn2c-+z1#g|PX7f2Zj$9зUu+T9312ǁ= J-CO$J̎3֌K(pzn;8PW]KY9j],}lA}Jښ^7!rcEbA0"t~=+PzOSAahު!}9d* '[:nSo^Ζ{y]Oʞ~hGb@83&9;'@bb˖7,+Ym@#hqFTT {okqjT To#N _`"nd'Vmfb0U\9T*몺oG4#-]@= ft NI ~kn5k@ܧ.}뗒.RD9oZlEޕO67-0HsIKsZ{n a\#25WQ=W12ݣl?L8_sskhT*#iF{ d KaHk0WkERJסhCjVHhQX܀>aFCZG6шhdY<׮>504bݍR?z EKNj Mmh(o?5aX A Ջ< z15~;DV^%nnqF m UKb}I8=;QKX ʞIgr c]ۺ k*t|AX#j޶ü`̸vzL%dujj>~ۓ@!y|w}j@_T, vTq֝nQAt׺AP6q>TIAZ(BMf J);.T$FLU{ګv$ TU0x6r _#ooj:+he[2dSXg'ҭv_DinxJc{dgǪh, YNH[ij!H ORymlYaI?z^NV͡7S*Z:UH9?ʺJ^+,I G%ިF ~@sZ az@rk=S y^Ղ/&YɢrŻ@?w /]@ pgʡҀX?z@;Ę1ZgN39ւa_l;Ίm2#VW2̓ҊZxyl1${UAnP7f&U[pp`A=-ea.rƾ"n`D :n&a'ߊ 0۹jӨ 6N}p&>j{|`њr2Ghleu`՘ر`c 4ƍ{L5 =ꀖ%RqFToۤUU$LТX"[UF!LM ?hl``,64=%gPmT.~35&F#(,ۈu+Ȼ`& tĕ"Qs5Ph2OS5@#zt]>JZ`+oS@,@iZS-=cJ->D0Mu76;'3W륷{!䅌N+`:nK1 Cđ-;W-? NUsD2EER +ڣDޱQ8m$gPhw9" Bڍr,2f@ P\cnS3$f631h[zh6`569̈խڗ7Y<3W Zڬ={{Q-X/s2 wv'}cUP*+x<3v_m\{[T@ci WP'1[zJܶ0+]c/ڻs$G5uGȲHX ƒJdzUtꌲ`?zƚՐ;`mĊ'Om8"1PqvHed ArN@j ŵF>s@@wK0oWi߭K`Zvw-n^jBx1aRn,W՝ѵk1'X_5wV om Vq"?XAE!{3[kpu2'< J՛!]F;fe<#)#&S&L@jͳMe½%XO='R׈$H=MހN 7a&Aom*{b&UX:6~JT \>ebѼk:x?XZ'_7>ߋ8fךKZ^׭b}:2",g|N8ʎo uy붸>K ZZ=5&M-p$2W&Z!t 's^&Ze'p$*n A惛q&d^]n*RIQ3kLGa\t  K =\}%+=6Ԅ`zkz]+e8Ȯmp?}nh Aڪ%㖵GO,YD֠+evH\sSx" t[3ڷԻ\Mz]pvsU}KjG^@/jSu{ҕ=kLJjMeI l0ao1 T6Һ7R:Q<MS-qYIQky%T3{TGbKOd&͌ nsz'$)֤N0&5o}d1_M;YUc?;M$}JBd?gۻlY |${d%}, xۥgqpGl+p@a˙ n' 2h- U#5z< Ou[ɪ+or$;O5q5+kCblMKN{p qD瘠9?ymMl=`'hU~+̸1^>a޺q\쀙$󚚭/V@5MD9@]`h"gz;ނ nH+(BAi]Uwՠa 2DZ5/nIg9FȴB~k.nFSIh'$I"NIMO,TbV5#ա^4I^b3ou#zƭ$XւvI%DQLt3dAZ\f1l,w Mfs:lIT{Kq;AR&w=OOj6'ʄ $B˝pfd&{{u5pzS-If\fCHgIh Ê[l9䞕퀀H:&a@[dQ4w8nݢ3ⲶlYb K.Ԛ?-wd@P㱢jVHX&gv*A4Nub΁I,}C.^c j^If%ʂQǷP|Oj0J@#Zr-=kбx K/Z&- Ks=kaUu!>b xOj)f}*][mn!@h&,m ݲm&y;^e&_AEQ8v[Yf +uIl;y4XSE:wWwZE.ʽG浏L G;֘u2C~Ilh5/h̕c+su;WF2G^{;9>FԼ#`7]AޡQ̻o}bN?,\'8eN<,o"IspdvЙf9 YmPyoM`bz5@ڴX}"Δ ?P^ZܡYl jh'k -q r1Ͻ\oIeRD ^׋ֵVN8}9?g\x~Wm 2 |O_NjoyOO/j fC ٚ]WNoraԱb+'-;m@F;E$oTѨi^ЀҌWkc5T:}pQ* cwi54BbHޫe ='T`4YX3X|^r`׭CVQp9 .#4a$AT$dJjqunN(G@R#$V6 M$5-A!f +D܆G*w-Y xS1=hXf B:[`k{O!4]=Ti(!EӒ\ڻkUkx> ,剣t"X;{њ+32@4-3!x/x {cUC"'tmB^~(POf dexPUkg҂Z>Xm1^sVjEqlѣ)57{"/ZxzPf_?^b;ITB2ӽkYl;5[moipE%2D1ȢXQkdoZtU Gb=~C7StAX,wwQPt02 SsIQz7i`w{\ڹ֭g,Xmyim( w\2PܸXgA(ۘch^%.Jm&0[>[֘*"TNbrME4ufޜUG1QfG9vÛ{H;f/'8q_6IOKOkS@ï'56;:UWP$Av]%{% fntpoǭV^faDv=fyxmN$ډYFʘR38TkNF8&ko얽V{2TcxNTv$S9IlAEζIP-7JIV:rwZ+ օ'v\㧳R \ay?/^o` 8cD|EY nfU}D0pu=fkuu$uo[p݌ːɬ<^#5V01Z}>|XI{%d a:PNנs_ `y P5qWQe] ]nYI YzԱ^`g=/H'Kg9LXʲ1o60Ep=`V훀sڂ-hX m}hpL b-X2LP澷޹rz|o&RÑ>Ҝj֮z>eN's@XEM.:)8H;3@;(F鈅y8"m$(!q=&K!$1OJQ" ĩ*!qh$I2_p 9EU3/uq@̠af$S& u ZU`]'D\ 1ڴ3ҋJ PcDwq^I"`6_h2 uOO, ZʹI?jۓ1TnJыlN(BYs*sFwjxQ }'v@ F{9ѲYzzuv" TA e*P nKkOFSp9sT[ 78hR$UyLςdhMLwlX(uE `;Hnq&bq _c0(-&Ngށީ8i_Q}57ݲy?4[jT'2 3V-EQ)\!W$ZwG O4TjpHaPEo <(\9?fmrϽlf/4eq*2${U]-7`cMn}@X+0s*RlT-&y"ktXsV,H3)^Tz'5qSg޼:r1P*XbduShj 4 ۆ 9 }AI䏚ic#چ 1_s$h\mhqO0ӟ:H X o5_Qi2s(Ya\DC2H26\ҥ6lGi0ʂJH*E FAFFq@9"8>jE9JDcQICم.AC s a'YqT]WZP`hRmd%|ڊܺre$0,p8&];v<#4eJ2#0`HVGуԜA'nAE-}d'0 7@ +r*8spB}۰n89ƯGP>B$t&+aFw?I;n)~s~*΃yQf\"h4-J 3;P npۏlb\#ސ1pvP,?B<)3'PX /wRH<?8hx9M}X8‚Z!{VjkO m UF;- *sKSV @&}c;Yk{c#YkqBڍpPŽE&O{Tڧ#{p9?lC' -TJՖHg$5\Eb$1ҳB{j67V,ٜwht܄GN(ԉ`T[މ6i1E0ulDrO53vfcSXSUf:M˰<>7,D_KǏ[{qW>3|i#i8inQu<:γy`GuH`\qDՋ.CFM,l}D 2:nhli`O*pHt0=bd}+;8f@b=kZA4@$҂邋j\1 (3( 5h"OI⁆%0izvPmńրdOlPIY4LI5cZijrͶE\gZ_7hb9:@VI[Z(8T9ڸCz[cڵMPjU3nAҳK:,u]=Ehǿ ht3FUkC޷@ ֩*zl3 {I ؖQX{)i2jQ:k@ ]Mzadd5ƽuiP56w<Ѽ6ABl9,b(ɟZy!e`=b+3{Q!Vd1Fzg6'IF"EfRѨi,8:;軨+z$$Wsm-~G^<< &$it4KCEL<+jҤ<kEW?] 0'qj.l">jUz[$zT/ߴFq5s~;yBOVqx]b pZ5˪l'ڃ2xӾh#uErAΩ[c0oa\ttO6ׂ@99r\z UC?S Zo-2c޹ʏxWOp\M;[pZifgq]1 ڔgR#j} 3V .IiyFb l &Gyn5;)$ɭ+Zrm"wsLf%*DE0ѭ>wQ032]gD1RT J=OE-bT =h-9nZ?hWPN浚q1SmwOSްؕ:@s%ˀ4<+Ӿ ʠhn[0>'PFN}imm qI{ yN&Azjn[HKC)9`Tw&Pc1;=(bEPMNl=& W_X40x {`Yfn1TM ATQ֜#HJl(|j5hm  "2jj0$4s޺9h91" lm]ggUXq#\rDD{#o&2ÚFQ4*]b]{Hw랕Qε}rY櫦JJX9bCGjrbfH\4i:TևfKuV,=lfIvXL|Wڌ2^n/ WN I>?⁶3=*C]F?5Z7mdFjVQLrJbʷD2: A⌧g|gީ"@ y$DwHP8#P]qUXA⊉HF=+C{쁤 ǵ`n+ %`{ߤSJ`ZĦWpְV$0 [p@ߥXv) j{y uNUkLq&jG`NcڱݶB, ~ }đ/Zʧ= ݝ166'ʮ 4lu,A 'MJw\U*W]Iwϲ}\t#\W$W*Fs3c6\35ʬkVz:@pz#Jn,' P55'pK 222SєגIhԕTQZ %`ʊ ^^C84mk" HAʤDsF@!QY7v6!m7#sYT1o,*Hq7U_&IP ī{fBтI@8zVMF;VP:"&gbH("NUSA+mqm1a@oq%/tc3@m#3$~>sFĆ2G5l;]TL:G nMźQ`*p?jeMUF]7OA4%L9!ɪp(2Q$Gn(vqm~N%;8h\Kmۀj&VJZ]C$Ep(fftKdb/t0Fіӭ5ēMXIfq jB$AkmMlJ+vw’}=ڨhZ`o:efL6 $GCE1?X:jݷIS]F TcEq޺HeimAAdd{WY vԮ۲ݽMĒ ȭ9Q Ja}AX-$HT)& <+=unYjyPng=AM7^؂'5,Cz;LB/F#nˮ% /lXKw.g`%>AX(P۷gF]d[,;p*}"5әNޜ*+w~uW(A2zV}WT1Ȟ@r\\ uplŬU1R9'5jsǪm#\qFcN :-F{n=!f*At aְ)if:}.Rm.^L?sTzv+t,|ճ"Ϥh rA-)A-e@wرߤu?lj۾bGX35Tr>jHarb"+hwD~պ[ RdUf=E sE(q8$z iX$wS,ܐ F +?bM":4>r$9F hĝ.Y&Z]E6޲9X0Кetieh"]PrڂǗ@1@9Yn"7w#yIlQ[WwhJc14 @F`0ӟ "yj7Fx;`9 Yt,nڍpE ;r! |jɼ}DQt˸;M_7nTV0{Ԭ+ζ@&hp]k`cjD\N+j4rOIN*Ғ GCCnel,BV]ʌ2 [!uE3_k@'pTuw㹠OM}bJArΨFOabkڅl5+dߞk+0%wKEnn;MĉjఄɆqd$0fWO1ԖuUJ՝) N95^$BKca03A^o-$?TbEX"IѪ7BɞQIF, *VVq9tRpOͯůn$)icf"F]- tԱ-t$tμ~q7i`3ǵ^%c*[a= ,7R$S# ;(i10>MF.Hz|U`&$*C;hRĞAY zW]#S~.q$n>k?GH[~I?֣ZݷбiN;r>kS݋wTמxܸʼnb:OQu]dMTi>+%MLP$Mh}Wb~(OPTc*Ar8<l SiXϽn%ۻ}1"VO2(_mJlj(icUFT.\f: hↄK F!^z h QF6(;*0k;Q`D)1F'0x=k0 q0M )ڥk@ G@I½+t?3wV71־y1u=-RRw^~㤮?W`yz X+#Yl[,O\t^!T ?j!Ae3@AkLm'N.FX=r'=@ Crx4B$A1-]#Ei`WkُB[X~) fHVDWLePA+ uGdZeD,nXrJ2OeX2e.3Fuf=WBu3GHeLDQ$6,{J;PTXܷ؞6Ͱ]F+h\;`+C$Q,-FQ#D IJ )]@4[$qHg *}`sYDQUHjE6/ cG?ւ6=;  $?[i4c%q+dl҆PHzf]b˃f2$ёn< ;Iz7[s[Cў;Uw 5a(qXojK:@DC/8<FѹE[ у4{w|Ōi2Z3,V4 3SH79CeqX-?j*+67¸85B9UdڄY%'+L:Q|b#4 5>bQ ^>PkMHhm˄zjły=88GgCch~+z W*_KWuuݛ&?"HTOϱm$GI8kqru~!jUq\uڇp fb;WNty[څ@*ՋkvݴRwX+ZٳkzVcR%#qiZbuު6Bc<Mj,TDԶi^ńo=dj)&DՀڷiz(+g9+i@q9q'YaE͜*7nzTuEZYYY(If0D18`}I3kpNޟpa h.[7O~(+ l(FA] :mB]\`G榎N&W\r3(呱jvvݻ"* b67Ń2dOaA0 >($spPz.mv }@m$vdR g2#[%=O128q?pGCF.fn<&i 60Q0΢.3=`uY.q[q^$Obuz{ Xu Ew ls҈Rwd3,\=MjU l:j"Rk3tT*(^R((^oY\V »vo N@VkA }Cp'"zI`wGHZ/VX=B?V3ҁ`,;4>ՀP=?kVXuE\yhPO@(7R N34 Ko$ m@ H9?,lkR ŋw˩EjXPHkjJݫg+1:81U"?Pxѹtk.I?V2RŚ ~;V:i$uoN {,&ئb$XK}V־kK{dI#854.8*Đ#>jml jDu6ǰ}/^V,,zrX /62O'SYy_Mx6b9+R`ƦTS\@$sXEfnH J(&d.UA+jW,֋)eP=d $mRꭃ**未6<)mq Յjה9m\Ok˳,A&DI9}ŶR9WPMo!rbIA-Kl@dp"a .718BZj.jY7LwZa9@ *ғ[e`@V*!*s;SKNX0X]Ox{WV=~MpNJ-cpqɪA_5I{I&k0S*@ԁ=v2Hn+5gnA'EEI;,pȨVie[sE$ \ztP,ّ .*,"Tk2BZRxq4O4b zF>GHc*}Z3 Ѐ-AEp)+ހF{=Ňfp/i=(`jyh6DGI!.ۗHR&B { q@UUvmy=; Pځъ1$=&ԚYwH]eS.0ВFJRLj,h" *+5Zm HPɭՊ lci141fڔ2c?40Ke̒&Y7-UYGZa\x9`ڵ:\f뤌K^]Y++_(T{z35wrXH3G=A*kKZU+j.ow$/{EsU:+HEKݺo P9 [&D=lzČAS`6\^'r{ҍl T%oF$&=keJn]$~[ Vɦ+C>n>kq:*@`9*>EfS>X5<)?^/%ӡ@n5kɨ@ŲDIoX>+z8C2 )jtZ(Gihtb #A43/eNg :VBƙl.C| fobێG?uv, H<)H@(kޘkpYeIZ ,+CԬ@T moe 3xn%p[+1P6&01[F Τq˖G FxA;d$3ɣ`Sh_PZjݻz| eJvc&gInޡ[]&I84-i/#jZSj.m* ϼR&&EӘj’[z4kjU7I .=LtM?z6#ҋWiQFj_gfO#JN틶OS(S0WѭbXMj[UیPȶł>Pon':tl tHes W3hBlXl {J/hv"geSKOR ?K5n*5κ' U}_Ϳgj{L׏6z. w,H9OUYTL5 חUsSpPA ?yאx HrfDV^'qIo`z@\eg֛$JY HV)d8YkTZrP356lpEi!NZ{?ПËzΧQnݽV~ս{ ?skU1^ʬn=c3Ցx$8n'\w}!W׆I1Ўj}t>h"Ȯ!4NMN fX*xGeg'jBb"!` YQE#F Ώf.'DF|T7@h-Ut2O!sQs];^zT)HS05/(eDz @]=@kHUAPw<ȡޠH[)&bvTi9чUiȬ rHj6)jIQcB[pfubݐ[WW?Pmi[ҽ:iA$ls-b 1'4e#ڪٷrI5mslc`ZL1ɊFU2rddֶ1q,6"js|a:P%- yT9355JOm/D,-ݔ8#0~! l|L8U;ɠ̒1lB]^F8hdv,'Ո[!.y<{/"CvȘjv?c[)H=i3\K({L{eD1h{wP@KWx$$/pqU%;Y0 [p-G>:T 0k'N--Ui}#mhsD})_m)3{TUnwY+è7r:@P(4Bj0m%?҂6@38kvsDTA=hEswiɢ ҀcqPmɃp(h#: `t"('cs>>(ؚF7s͠ V 4H*9=?wvO.Ω g=h l.O?4fnK5; 1>Q0'*hV6'mAb'jWBbyRͱ2{XE ޫŗn nf Ef4ԈS$u3$(Lvn#tI{w ~YE02 ;`Q%AZ|Ւ;`ja-3 3RMSL _f`Yd'#Z)b^Fy*p1l&q["A7WN ɭfl PFizT7o;Gh5hu w0=g?z˻Et^T/@n)fͲޑ@K Fb&mLvs I 4[~Z'2jt\xSꭖp'$|qS_Qx[mAhKh2AӲX*jJ tz[5ɟ;jk+5MnýXv~jTP9MC8 or(ʕ qLժCGkÉqn < cR7x$F)IH9 0/2Z,I?V?tཱུ;dWǷjޜ"Ԥ4KڃZ%6{:t`NCSQ2 g5garĀH׃1no,nOn}ǵpv-5c[DK!e􉠶G^܊2¹e@D_XV-jA?ڂ)`wD a) u⍈0{FDy⒠n1j,c5@N vc$`Qv|*ܑX]@reH,lGB.w~*&)A'gi+6ےIgm\>`f,3%< )l'K`;vTې`sQDR\vh- Qߜ0tRnLPMȸc-eT:T,zĀb0;ZnHm-#>b>)=뗟kDn/H@zpp9bXHhSY+_7;zb\[nB p _7"@_mL?MpU^)\ӽ{r+qK DV&mI\BF- QzṀ ]EsU*,S2+Z5ZY6\QHA`IQAՔs()j5 xdj5lLVH@+8i`۷Cp!GX#B w$jFU՚)Ak5Kr8;0jսš0!pW2ˊ+61jѥmv·PmEnɈȺp94u6V崬e3sA,Xt*B$$?zK{J掋 `p&Zt:ˋZu"?#͟Qx\bwunV ޑ-]6-[rN$'g5[A9:fg~m[ ASX<GgUE<[&x=iAL鱘;Hż3,>+c+U/v8?zYFq|T+`g޹ֹ u3+k~~KjNQ``OV[7sѫr9=*4es?hT1Y%mA]ź_ӵ$zľe#x]k$Ǧ ӊ|@7`ȭ:7};w1 G&jHPA~9ִ4M"kc0Rb`S)mf'w-@&+0L" 56A02:r,4)gb<}1Sk xptef,iaz3 +X 2%o?Te>z 5eS@"hLzaI捱)G{kTLC^t:]CY;e wU&`؊y$QF& Cy"WVM*ڹW7HuK,j]! @n1F u:хcxU sjB[;T?5@7#8! A#}SldUY**HMq3k@1' Yh_>I 14 Ł3@H$ѐp?z2OJh-J~TirAUfX*aY}DX,F`-U0id9މVv"ɴ(<[c;g+)|u8s `GzשJҭj&L/8ܺHEn7ؑ@ϹCzMOf89{u͡L~؛w7P' Vf..n I+I3PR."qM-ҨgUho(34M`8[PJ1 5=¥stNƢ2w`5qpۭ(jYR&IBD;Ѩ=u"!S`T[B\m3Qbb_ubpX]6.!i Aa֥;):;($n8(&\9 vvؚ%P[Nb??zmSs@53n1g(QqQ }3:`WfsN #tHX 'J I86`ȩ ΒOڨ-<*lܜw/1+-Z@&0fiw4mK.R 2fPYs'+@)4,*鶩$ KX )5 uCn<75m-SIڀ@{2+l4LmO30u 23qh[ʋg ' j, }RH0AbRy 2adt@6r>LP+T䌚5Xju!D6,+\Ƃڰ7l1L[K 'ց\֗D?Nӂ$"GEfŵ- h1&XǕ{UЋnXH竚l+"V:~30zWR\v$ǿ3Qhuû~xurm -bq vԘ7cղ.]A9gNwyR5f qpZR #iH#ߟ5 柬ey8/Od(U^=|dlh=(r n\6Q5wFGQVkl9]d1k1SK/#L_HrG WRLtTFIɉ+VE9iDb{hdPZc$Υm8ށT=5˥#OSmQw3. b#[l+[ajKpAG?7Vm@rZClցi鴀+);ѸгiO#F[Ixg9[*z涧CM3ogXY fєk]8ъ+AZ{z:,bH%GZʭ}m D˹piMo(ē4 ?F3.=ĺa5Zdh)m2Dc?Oک΁G"W`R7::n.rqg(d`fY۸5.i|rc- ۔ZVıYjV V^eO{!_zOQ`7/H]`:++pOڧ@mZe9nƱXwWpI [JV/2}/GVw[!s_?2cxV$olz؆I#0TfPC.hA7H'0 p+qШg&hn B, W~.9-anziu 'icۼ DY[Nܞєʼnݏj+V *Wn3jZ "hb ~+4Ks!4j5⩑UjE@3=#4`fh:M +84iEH"ʒH@c?AN($ > F1 2jQܞtS"ʟRlF 1=:Ճ$MlJ1kr?vBۈ ILf"5©$'4MՃi/3Hv?M+5Ϩ^ذȚ\vZv8k5TO5DrUy{OEU{ѡ,1Ҷ!3N|0ZDH?j]EU^P0zYDdX+, w8@u9m$T6&>5ʖAu[hW;l[+mm9 lP )=hK~ A X4nUf#B(h"TƀF`[{rr}w6k4n!Q5Y}' wKK9[!*w<ֱ+:@S҂qƷaka9R"l@NH0zrn*րzQkpBB=(`*N{тP h0diXb'4H`==%Ar9'leL@$NkRn noPŲ=hm4 ꍦ@s+a `jItu#挤bjaH:ۅS@\`j Mvmj*-Zt[eaL80y w-PƒތI-Vsj5)okC 8u^ ,XvL~MbÀqVԧ!OƮ>e zWFc{7Vm"9[+ Y}rTތdxyBHڦ̽T5L%PnH_@fVʨ%fo*p LU.MqF4q⭥sn+%GU 7 =&6;s5<{j-8q1ViIy%F udud/)VVRXǫھ9VQn-$ W5˽O?zܵfZVu׬W>- Wyw2`tW^=klh~(VݰEmǤwQo 0-9# GGvV* [>;[o)X,y7P1{{ȜO;hWT:--9K^%$jhw$d54J'"HV3QdǴH=`U91VZ"mOQSޤJ8ED]|=5vXv%7nSt2mGc\#pb"[!7FLll 8n m;($t0.Sp]F<0{P ^oމF걶d@50jP$Oc<(iʾpW3$wicpNq ^ĩ+tUfb3<W:ݶԬ3YC.\~d VhuR͔T<֬k>T,j ^b4zLj'DqQ{4srZLj$ z`1}[c o}=kYE N}%bfi47<'Ph5WMjʻs\,/.KAҨX[]zc?_0b;ru[ d5ή*7'MMt32 KqVa1QHYb%%(pfC@;&2&gG`K8ץ)Rx(b#bI&2̑CCEcކyV\\vݿ3ZvX^[-!O~j0K0@$P'\I^ uE@bfZ6ݫ+9 P0\r{ G8JI8~/h LDZ aG2(pMbAǞݨԑrU7nM`ZJRL&+*Iȃi Jڔ%+YRrAC!CGEbiJ t`ԼX/z X;p4C=y1 'qq{lnQtTn2ke 7#)4n 7uda uE,f.A4[PG@b7!m'*~[]i&(b;̻ ^Kh5 @xʌc=j74glizVwf&g_`r0B5M!ˏ4ezGB#2=#1.EebP= l^ TԋvNHs-{N%p:ձܼ5b m`xNP[̷j1Z71ϵNsR5%rTOP:SPdZOGη *yQDgk09k̖mzQ mF2$ۊ Ղ?j`h aQWM6y(+Z@1m-ۭջj4f89'|2_I D_Oǫkf"꼻@ W8~]vR@d[Y- Ga=1[kK)*yL{<\c"歍ǎ_>jLNdsXŽ5I$sCqSndu4=C=%̕)jLsJ 7ұV*OHpA% 'Ttݐ}Y*%a22(եkͶ7XG3h+tjʰ ZpBD?z'p#nZfV#"O93jtiWd튑yx8@mhq5)^wNqLrQ'9R .BÎ9h-M-{ bdby/e iDGZkhnՇ&ϔncmYD@bF=SNK(L81 TH@\&Iu XWP[`*ehp[Q .o4Խ[nߘ$+p M݃1ְ}]!G#Ι|2J@nj! Q5\DA,2`Ѻ"NO憆e[Nшh iXwtH:on`TԿ]UK; E$;x`_|PͱZD,NElju7K;Q~ @-2n0qUQqnaZ,oդ*z(,Z&`v}C8 8[Rsb{tnf֚&ѴÒ)# h.%]5eAI*;hbgMjX:Z.V1AfMh7Q|kdۻmՄ0Y דi2zT c+Sô&G'ޢ'rˢד߫O~ ^fO'^k^|r8ECi~ xnzwω$0faۀ 4x$6Oj1H'լW>"XqXMe3*)zg,GϵucW]+^&r~W/1nݭ#h,[<T:4U&)`AsT^IwH2"E}5F`Ґ\e7BN.0 pH<~j jBa(V>JÅqT.i-Ծ <j7t*O*]8mܬL*V"kX_ZC`<eV< J5_T5F{[P7'ӼV9mOP {@7"&Eқv7J,f8#)dlpzTWSo[8H{F}u"#ڹUUU,NQZV`qRGVCCTu(C!1PYH1 qrE+k,yY Zcq+&8+c4?)/hph*#z tz6PZ1 M Sz Ft}0HL|24chKM&H;CȬŋWH ԰ڂ:XqF 9B.3sFݽI&EGR9"#{Q)|z1+Z 3V6;P=\(,%6LAM6OҀ`I.vqs pA4 p5Z 8#A-1A5Q~rH`@ҖϚ75PY*UUI qR\*@FT WМjK~";jf(A w8J`b]/FyP{մ0{њYlH?:O[EQ=z0&=k|Fʍ0cqM4, q9#]}J&0kU5U{-ak}g՜5.I85om1STp~JLȠ:A3@}=N&MbYGlԙ1 jI!nc2 o>; ~*CY Gz Lׂ['-mi S?ھՍ?9ꪫ$yg~IgV.ߺN{ c][<zy9y=[q8;VݱkjZ {lTd%'V2F9?u 7H`Z2Ѭ- 9$F6Ҙ݆nZ릠#đɪ7>լtdҍH\Lt@v,ۘ=OA7V.jtTQ*gXn( +{|VbSW ,P:`*15]&Z,ZkOp*lZt+nP>kgbhebp#p↑MUP gQRoX֯oCQk Y1 D0b Erݵ &"<jiNYHgXʯv鶻OV-1{a`w}ENO(XueR8FU9?j)֚q|U@A\71X4PPdN굦bd?j'WQq=ފRI3ڂ~qGJ$p,*P\(13yIPl=m;`zb68=)YU9v`> ڵu[)ڽZG``c)8AwWq,'5bc'z f1=,[!} ;KU`ј$CKap'jkVmi7sj S[yTD}_j6, !~FmO,y9(;=0zTѴ:M8v߉bG@*CAsFz ToeJ[q\i0\L&Ͼ+ ":~{dQ} 3'uq|keR`@[Vo_qyLk'/oK&$y7M^!^-E8*7-?c&r/|+Ltۓa VׇxbV%] cp?`{[)+[T3kSmT"뻄HEwPӻp>jIF{ozgⲘ}Kcs-yC9On1Q//yRELL>j5KOi4e |%WTFD]q/XX2(a[j6O.BXU#rU]-~X=*2nygs'-c|Sz*neYV2fOz+kl F[)VW1ݩ߸1Z&JۑrGPՈu'$јyE(`fӮS:ѪZf|޳UKIiwCg2z28=HPYK>A"*TB mn&O(ļBkq"#8yn&l3[Pn{ i ۽FzPfZlr U ^Ӵuajn^+zUC*%usn+q1cZMcB @ΥGsH" ׸eZK-#1H'̐kmvڟJf:ԇF=d{~G8Pތ^Ǭш#:{DFgh.HP2DGލ`PBd>1ލBӤQ 'dr0zшly"ՔU.Ǹ@wUQ"sVʽm qg[{ps=h,b=[s]ysyTHrO'Ck;kB`}5˧iYmƶDnָE D{U<.[>f,{DEaI<^&<˘2} `sT61E6^_M`#L.2=- ,dv4*ͽHMpmՌ B>VJ+[( [f$d?֌5+ [nl0Kmf1ނiҫ4lX]8VF<'H|1Fh- bH+q4)u]OXDk; jz˾K+#t0Mh?q  5s7f ޢknzB("L:t:0`fkuie 9";:bœ4bAf1^rjmWjQsږcbdvx&Orm6cl5Ӫ\ d i ޾ß'ɭ4mgn\؁yԫ$ FTrD~+}zq^!p;ʟx<{=νpʞt+{&K[mfjPh -wV[I1h0r8yxm4lH{5;AA+ɤI 7Y7\4ڋt~)5mebn":}Fgm Os(3ӭ4Eփܜ5M|_l7`Ԣ%ֶAwSVwOv#RLNu nD .8jK<J*+߸I)>j#ҍ&su+:,{Zu& Zq8qm=$ D횚GHfތ{)ff4e3@ H(J0G@K$n9F]ӗh1> PA;z݅eܧ&29X!vlFXd`#, ? lH \!O\fLϹ4n QHLƠ7OLV%Hz%VK7 h_1f֪ު[ X{w늦)(ޤ @Z$@gi `iN+z?z&E+^Ԝސ{ \ rL"j=)ppRyAb 1UEX+Dc+"hAc^˃l)F$r=++pKV-$&H\164]N(ثqq8U(CA1zb ׮@cF԰N~‰1 7\ֶfjCjCjFfv*`٤+L>4eWnfZ'B׈͋ncvÀ6˱ip@Wd^?Y}[K&X}z Wg L't'tayɓ<{[^w֭fڰKОGj n隡Eu;P1FFLr*J)u[@<quO鞔%!IA榚Vn#$g ~fF3-͌`K(R.7rr}}Ykaپ;2}SZeڶ[ʹ{[R tOW:t_$U&2&5)pi`MtsZki1^m>wcoZxb`1q֊j[P70A5cthL(@#]Mml7cZȅ]ݖiSsXj7vMo]A4+~dPW7û3;jZL|i#h$qD & ި)Iމ<HQ*90/ A(([Ͽ"6֨ wA6Fe'Q&hTbpwHR;OHt TPl ڼ1amˏ>U3 GJ2 #Vʈfj;0Rjśu.SτX)(x>]%8]$qқݘpN#j\y:s9mujkVm$F+ w9=̡96`7)fzQIɊjbB7=JnBB*TZ!*B&hD ăҍ6$v!۳j%`0Qkwp3F.Bݜl@iBwjܛqwi e p=h1h+%{9{TՁx!v;,/;T ⦉,b/οz0mfh?~*@n]"JŽ\RIgXiJGy[Yburk v S0Wv+z"$ڨ Ara~պvgknh9y2ۓpڻ hgTIȭa neS}CҀ:Mcs`h5.J\ZV|ۡ@ʜ浣H1zD$I(Fe~&!ǴKNh`2$z1r"جAͅR tlKN׍DNx~ݵ"'5/@] q~IUȇe/({**euś`fV[r*>v6n2'k]\82n 9n91\Գ*] י-n3SW@p+ +2>YmFhJ!MQ_SY{`nǵ\(('[W}XnT?4toӛn {DɯO\<Ɩ׳[qD_s$|7K+oV"Xb1搪^LW./'@c3?y:ׯb1ߧ .\ڱҳ @0$ڍVӵgO4JvG1R ~úm.s#EjPZ }P9{{ZkjwUhUS15lŒH4![cYAhlL`*H&h+뙼60g#KqbBwāR] S~{QfILGFhsMRiBkY@x2T?j0Hw1OY> i5*TH)8 Zʇ7 =*X.l =9-JƪgA _hhAnF5XԟSgp91CKjCV0F$?*ߞZ|4@4Mw,]OCVbjX`Inʳ1怶כ.zM1.lip6 mH'$r(mC@f^7fTɻls S:dtnf ZU,ݵKӷf.܂eXfE6cl`^˶.A3[Wl1='kbj$j~SnvJ6F7GZb$3W-i|ہɈD޶E6܂`rG:ղ w hJ:XV1V2ԂqUU]nd{ְ;WAjdHhk.}Hum|0Ѵ Kuw ;m]+0g[qb_K: ŋsPv1iBY@xij-&zel} D|Q j~>ߗ{WnjC)cx{%y;*x5Tu?Pj ̢BT벭v2J5e!I#> m;U3H*ݻB$V*mV9%J̃ ۆt•vچp\k$Of³>ޥK )1Xv NzS>n*#8Mu" : bsSp lFoVk`A^c$%9v[D5]V|oz gn7 | /b\8%WshkaK8*H^`h;Bgڶ2<׸\*wbGrf{MWuX8@[bD6hm*C; mWn @e@Jl\akYInr@4Jvs:ҊNڅ%Ȣ$PG>\DOSUb"\pXgtS>kx^/#rޚZ@^&GX=T KO&k\QYP7rq 6W\"c3֢EWW[3;GTB\)+6Y<(#*@(,=hp0}NHǽ;m[6mޱHj-*DF`Wv1;o8*~Hlblȭ[űQvDhhib3 gLfXtGG5iM](ܠlH1=ؐLGsTbA2j]Yđޚn P >-du[bܠFZrTsP 1޹qٷw?nvڱP Dq:|.85\iF~T mCY'e͟Vt5рp+0-2#X!zʨ f% NjT=Fљ;V)N.@:* iqei#8n$ PEq5-Ō4hX}7;<|kİ=+SRR ǽYjwj%ourli3̖n*=TJ};]`&p?Έ̃=S!5C/n@T]2)J{֖0 |EhFObCdK#|֊LΚˌ}E=|bz5]_:Kz?E}k6?ڸHX(ğ\amOzV `ޥ`NX Z&n cVHAZڽf&XVwҁ\[wX#47;f Oy60TX7=n g(yr`PAk*s&'2f++jWG"/ = uh c"% mHE2=uYXH,#@KerN A"V0hZt;84CG=VYJNؙ?޶ $;P" pt\3s4f&-ү3&dO{OڂA[Pc5u;K.NZC(C"I ;>QSpcj"\`Ic559IvOJ &JY?j3@.( xe#( lIOkz+AykRSs͎PkRɅVVUw@P@'z+tT0Qdw#3ک.|1WOmTt:ŠHq Z.OuW5 y'$`ýy٠8v3 ?KE(cڕ9ߒZV5uIEzIzbq*0$u~*Mfj`@#~vq#X֞N85R}Kur}ZZ] b8EBgIjA⡶'lPA%fwc@[ZTZ}ݠ>b+È84lXE*=a$R$ 3DѓT[i={Vc yeHQ=kd[l \-w -3;2\M3}/nm(:ͣn Ai.uN?b F9j[os4zu B1$/鎑pOAYY|c)2C,g[ j1~DnO/O{KSmmtsMCHˏy 7p3Mw4L/;W&/`H15'8OmWdmlat  %8Qӯލ=kH%m&SKR 6H3@K,mRN`:~+ X* }ʛJ--:-"DO#vX!ZaI$}~)i bTKz 2õ}|IGQ5[x(]TYƉt:Q`p Njlyl:ֲZk\2Siټ^Eb6GZW:@+ujYAձN&QXy֭*ED[w]UO]Ăᕆ ε q0DVbgO;2 N4]E0-mXWΝp'n)V-.DLޘlH(kn(VC<*lj6FHEx` \}2b?z ]~#{tf䚡3)qqAXfeN$:PþTpjAEX*; wIaz&H$ Q0Gz uew-noؘ&z)&/603&QmH>ղ4K+ wdI{@qv4MHX5ոO$OĩFߠhn EV$z0J[[")ֱf_<^ͶD| F{V hZnI5zh<^VG`xp3 –$(H5[@ݜT{-a)5ºʤڤ{ rw<Wn@ BqEYYDi:H94nyL2r pP;0IH#J +cҀ g& e1LV"[sBա2wE{OKxa[ NEbMm6?X&w1 SZ[ R`ǚtveZU]x %~QkstNziȂH]9s-!OGף[aFMˊsŸuvfqknܰ ـyw埩fr5p!ccUw\$jm-:t)-q ~cZeY0 GfƸ8X-a28hw>jF6PHH/1 Ͻn(]=ݤ7^v*\J-8liRʛA\qn g?z`o*޵5g*kn̪N;}@n'ڂ3GJҴ-zXezm#ӭZZT74阭uѪ.AZS둀>h:n'H7LIֳQ}J[X,h{D 3Ei;E iؐzV`]Iە=ʟQ[niߍ\lvw'Z⨮剜~&_VQTk` 5TXnHEǿ06{T ٻiЫ %2$L Qe^ ?jV@$CuUA4mx-.YLcCSHB aA5/6wc4j7/ h .A0~ x"9= nF;ѸeH$фnJ^h01zQfr5i.PzN.!ǫNn 3֌ %I&zOPvZUg3ު;(m^d;*ޫFɜ~irېA5.- tAbʪb Xt)@mRG4R sȷ8ߚ6na$PϘ<֕W%d㱬eqYX@/9EH-PwzM͗L3^zD[bNL 鉮NB %DԤsڪDOV*ttNm ߿J63|o^uOչOD.T}+\=tF \n0sZ0cO@8ȎTKNX9Mt+cǘT|taU9Y½<0 zS*cƤw0aƝ-rLn>F½T =HqMn;84 keYZȞݰV?KL P*6>X`-ņ~?lś~eTqrg<(ݣI2;uUڢ?98jme,ٻo̸:ĊƢ.D팃޳CB)H޴6`4= Jfę zs$8&At O@h.x7^; :JX,A=LQv{s1ֵyV6²霐>n,x_ՌP%u n @Qւ˩Zk;QiZu9x!Vִ ^.w T}fDGU\i|DbŁjn-zbO{R,!ޱzλ7d!zE]/LQ$4_y{J88Hz/ yW%I WKeH&`^'@x`.d95(ʁFMyzzi 8 915=r9vϧNF8\RHxA =}sT*$jjeޥа rzыV@5^[v5h`5:Dx Rş$FZ@چϵSh qYCʀ[JjjbV/frA;MHV!U'(ofOLfBb{Uh MeMX{ԡ $D A= ^D}yAt[a,[{ѣYK"ګX{ u$[~n# WNðz_ԷS @"Q{UdY @lTUFĸxkxr aV?t,6/j9RݠQk.IiN=ֹu%Z} 3uno] X'#}7ʮ |~x*-jm*k4Oh[XfB+}S@щPڶ ;XҾրjGJI ~$Y6[hGzt@?j1ҫ1fNN*?pPYoYزVf|^/WƢ\;M{M5Zd 8#~).|W5u󵙬כ6)]`DʷT=b֬P.{v} ]uH^D浕;U3Bt#8UR-Y O'r?*0Iݷߵv_hʎMhN(2˴ǽX?{jœ:{P`m T/hhMxKg; dIDQ+ډZ4_jSXl9ѰM-I ſ%I?ZBU9ßz mE㷵n_qb@MtCFX=l jUhՏ ӄEv}& {(%z(V}H2A);"AYn. l2\a gjT2*ubOgT-bKځܞFʂIQnԐagֲvR#=8ҷO}YSڐ]ӭw#sւmTf'eM`Y` xo-",~6@5bv*ɁϴV5bۨ ~he\GVmʖrM+T{_v*vkLToѽxfGAyS{Xq=Zq(%֯G$ұaIT)F$EPXG˻ n5i0%׭ҥۿg4MB;~lT1 4M UV`5IpTM-b2IVZحxTvv%x/n^ "w_.у.g5# 稩TUinN$͏@m:Md5R7zTKqz:ObH$=t?m°kJ*kww \Q"]0 Lh]u@gRyhX̎O׵hPZYC3Ec"]ܲ)$Ozcx;[>^1[!z}[ZY?Nq[#jmcp`c7ZH^1CV6F3Sɨ{]"fb 4P^ onCmc:< Oɦbݽ4K`p( /6PDj fO{3L`ue#T̜huv wjY@WqA%SnKԁF{) :RqfI'N ʒj& .PHhRBO5I~I &:"lR`zbH=bOL?R'$:L@A]RwO_m8YQ@ǵ{V]14Vz"=Ҁ kϙWEbnUF5bL";E1Pn$ArG4ĝ՘ MHda9W4R'+(L+}֖&CN8<7P#IMM`wQ@+ 隐VC6 X 5zJıޤmx)-2T,X>c5q'fo.@foDEtt\0VӲ0SKB@yfMbp5̊Tz`(I($#@s,>'5+Ch{|; G@K-Z R,ٰ,+$+bhGr a%ai7RL9kMEnݾJ؋RSۀgZ4nc 91ǽ^%i@5QV 5x,T=Z4mmbr:APXژ ͳkhZ+\f۔1۾bhw9dxG,:tݽv*(nr I7N*$z֦Puڲ ~jM2]6@<ƀA]=(؝ݿQ:,KI4޹p\@j P6`;h 1DnߩI5Qu \6dmy+AӂcfWA5YSƁ-ʇ=Q%PA%A:Q f(kO2I+߹oP+,sA+V]s2OYikb+…WXaI]YUU.ޱ"+mo,ۃDN^!~&p Xc-p`#3/ֈqAx@9j܍:v nG\R0'pzة˛CIȨR4BzoM@^皕!v AYic%6X^Kʜ=nh 'cDi<&o]aGQY^[L; U '1^nO&}.-! pv~_&=1w$Ɉ⾆fܺP݇?Oy7%ۮ { yWf>J+Z@'=>>/U Gdד][|*zҘ49)'waȊԘl@dZp*AljTӧXG_jUuvtbքnI]U-U. SrzUa -ԓ(-|挡 fpwv{Ynp H\lZ7 I=nBXҚ洷nZ2qXKrEZ}dYƅK i+;$T"B>fzVkd ϣZ{- oc֍+ ?f 1Qֵb:k%=GceʹR;SAb=Hݴ0,A @ ʁPΫr2w1*Sp0mӑF-9'AK WTyԪ gtj{ѢݺEl6}`CМVhFbIDP *yZҷ mZK?+knߗF#f*A}Yvg4nKjtӓlMke_ޠ`p&I.szEk"¥4P+h tۂ3M!*k?="cP-uj|CKҎBbnLԘyfA-lz*5vލX7*M@^Yqlb_7HqBWd2I5Xi1{Vqw{m+?@1z5J*@k( 'Edn.s?,HVZ12=R1h, (ZX INj²d@1G;h:p 1[l0qco2( 5Vb`VA5sqD*c4P>A.Xb'(*9=*2ۘkVҪ6.dZ/X}. $qނܾa]:M{NbsFҋk# њibWbuN"?ظn8^SWv#s^ƴN.6@B`TXma;csnsY ~+vr{;<+:mRAvP6Ysҍ~L.$GAM jX$. P )iǪ$"1T" nGl `A;|A]Vdɨ Oǽ=$q@ia["n3j#2sV.֌ f%A()YϴQ+ m?5`lQ5sNy>WV[aʀry`%a$L]#luЁD5|W[_NmBH3kqF\+d'GΓ-jX9^~ )'0G d*Ur{ԺD,)K#nr]݅RD :?,<ڽ\[X?-mP%$2J+ǙsDtTN&5n@v/N q߇2'ϥʣq iJւ6 C. /ߟހJ .37COyBO 7]ͳF|#rQPa*⃶z`+ `mEH`Wff<(F]/O~CkȒLAh 1 M;'ZN r.4[I"p1Ay]yO;AFlhaPiGS15wJzV۰nB&Qd V*@;(kojBD 3?U ?H9Y8ҊS^S@1qP(-ں(GNFk|2\q9AokB2uO}>Rj<]qՐ@OHTuڑjp⩎;[t1D#5f: mBx*ݺj箘]DHU|z1ZR+88YҪ^pd^jŠNCW=:yg!hNfXڂѸ.X SȘh s>>!#gt"p{ȏkز<^{ڎEO8TGb">+8Zh 7ӣ4#?j._3tn$GwǽymKc$%*#bѡ[{a7 @ތX۵WnOED`w HbamvAbkw!_Q2~(ljVīNF-@Eۄ9aFqsClߺJթr°4n+jl3hbƜ~y=e1j[J ȭ`:p0[fa-@.z oemrK~ZV&86<ĉh c=0X==+q-:mʯsR/h 7oK11JI O"8ԁ*< n܅#VC,H=; [rA3҈7VaR-ٸ\I=(*BF%eنO6',-Zۓjgf?`h\vD`jB䀧8A˦4N 4ea 2z*VvJEۓCLM[$RdG[~eS$qF]N˹N?B-A,̚&uR kp-$W/,o\G?  Dڊۍ)4t'\3n潯"[d^Y͘2GȬ$m@A=5Kv4Nw;ѱgMPǥbD ˹glIDmEhA|Px)_'1F <ǵ-nBƳ5`0 *!=h%lqDMc2i3[O튰Khw fuoO{~Ycgru& FtǨ9buT-щkefkdjrv ,ZDuVaOjѓ-ҼAYW4;$B8uNk|>7_1W}>|-*⼷ľm.Xz{W\ֻNt+,uBE^bCFޱT]Z[V$'>\Mf]hAEE=/µ;ve۷O _/x[]cM-޸`Iu׶]-l#8Gn1CSK2O򻭴?WHo]:kjy'މ&R.# o :5XP{M>-"cabv!zqjq]f2:c]bV~ѕVּ6!{ -qjF4UOJM.sDԋ<`Ehŭ۶{ѠBۀ(+fr"wF;sF,i>M BV4eYYSؘsګ$A)-cZi-n# HzĎVc4MH'cCfc4W{rd-;G(]nh{V=K@#1ɭ /uU htեeTZt&`{ѵa4^\qǽlHgF@V,ArzCѴ0 ?[R  ǵl:Og;1Mxm:yvbd^9y{}~ʐЀb"?^qyqַX#bܯ*]A.>G+Ѝ3\,w\V:rWQd6OC\ @5P`); sց70cڦg@Av5`)STE`mDfЍrV?yz*Lb ކ{`)'RLѲ"8;޻f@R:u[lI2zk}0yjE g?ִX4e%ujE}#%eR1#x4g̥m<xMZsu%?cRF]]"1OV;Oo1U*qQROl: ^~ v@#A6fO ӤsznaWF¸3?޹grj] V /<CG=bz`Ik`(6ԉ'߽jL l38 ϽHo-dZs"֒&+ֆ`v Գk6+3@G" nWl*i=֝Vʂy"OZW[RH*bWv{uNzAKG~hR{b.=1kMhйB7c:bU7@"+0%1=j[ .oh6z1V[p08ZbSa8zU%7%;UFbvXƖ޶m+3;ȌOq"ںM\֪Tex5qrŽUF }|犦h5 J]6FLfKv4m>f Nk%` bdt+{wU8#aȊV:{6yIX\:6čbGYU:+#ڣ- '(}PUEbNE T$4bOkO?4 ܇A'.)q@fH6*IEVh*cAa]>ɢ7 ||ˢQpI'@ j),&jTdff{u|{1T,UsA.r(% 0:+MZD">n Rr":&-*}DčS[0[J \sQ*ZtҰ5co$Z.{ilB.qQP=A\3T?2>:]EKQq2 4HFچ@(@*J>+aF'U&#*yȊ0 3b0!>k=o3м/J9xj}a:sBN⢩xApQj^G޹T,\6Y܏8"C3_QPAfcdQn6{WUܹZ-0h+ Ie tmx})pPI#5|$ʚhdҍwDֱҲ; u9ڦhiRAlW$׃&6@#{XYib8fcQn4*.s5ʺ"uC1:lszcv0jK}5݌‚B !_PZؓ4Z!ڀkv+ 9n ~(2 =1j+0C`G4^mP<+mVNSk}`kh5lظeѶ1&kP}HӃ 1=(/Z-Z,3h6P (֟'sEdܺojːAd&$WaB[+3D w=E(2vb:M.jcJc&ApJ`Tg4lSjїҀB-vרFrOcFkX8MzKē*zb :FP)'Z):JjLD{֦mhˁj%I{sV`Żt$v"zbnuvh7V(Mާ1X,(= P\G7R{ =/pAV尫L@5quV,j-hs!l`77I@~EiЏch@Jԓ=ztP,h 6 !u?֠~ժ1_Aw (A?ڦkx`b-.ҍXB3G ڛ#Q줟Ѻ*2 5Q ;L1@ POyU Msm n)ii ĜvkiH Ot]ǽ]n]'WlMTڑS( }YjZ%H1CV%M6隚H ESs$MN1A pĚs:EcbV=z~P{`3W4fmeW:3R,`\lnk/S/ {ze??:=JuyV;{W]QXU[p\ε뾜mUZIก cin=n-F$HK Oo7^!xn$a޲~mm9>2:zy>U~Y``Ta+ǿM{ĈӝTI|s46%1n u;V2 F:iʝ 4Qwu @,mbE~1,I۾ *UpVyԬ] $d$[p0$Fk+q$$zb%AQ5¸ ȘI42C\ZL qDf?XYo1P~h[A؃4 e7T=`f4~]w\H1~՘kKK*%팑Zh[F]Ljh_-u)cc7q)HYV $+d5f߇yih-20+99G0.i^PaG^wüK[" UiBWh FHXKD21 i[j(W􏅕X:u|I!%H9z~sUdLuڀOm:nPKw&:WT ^-l&Al7Q,ZʶU_"~^ŕOj)Jd;PLbK7^͢=DG&Yw6Thka +Tq=kP+;S@"1ɞS*3EJz6+ D1=OeY2#2uF 3ѨjXpRWo PWamI!@nZ`[4 %`f@鸘'sF)dZ\A?2-=@?xeuء8OVy^\;NgW"+oj*u<.փL@9QZmLLc/B#9T9=mz1 OI⡱ZdۜVU9QmCO?⹺8^-t*V~bjP]!C HSTd*nz+N#fZpۙL=ݽi1du =I@iL(&1c1E nC)h1oA9 -yтcjԶ"kms={-s~&3-N}BW ^Lc繀Ep3T_i_x 3^zHw ]~>+`Yb kqcM`ZBY="h&⬰w "d +nLЊY޸odDNd{P\]*tY=;Q8⮬OJˍ2(I,QHU⪩ [=tn 5bWm6g2xn@s2e7-۲Q$@撱J+l'?z\Y@ݸ,$ 6;>`V6{ Tͱq@@T:UOP_YMl[u *A%c!f֔2=V5m?%Ii/d$ښĎe=C;croN K}Q޺&[oCԤȬB[mpȊjeZ `^eVjrrYOljxS2ܲI IkNܿ})i6l {W+vFF7V m'g/:6}+;51K{J5IXg_]7T'Z+gKOO)Q|,3R<{3⚆\0EQ#C&>+u~Tַ_a$z5s1Oe=yA穭XmabS-??ҷEMEGMXVnց-q Q XxLSݶw)3A5luY?n'Rm3ДDԅiZ[P +Mi\ ߇!@;؁c4{7t$IE\N<K\w~uGk]=;v;fnky_ՐG&kִV\;Isj1>H$pqinۃ^j#ul]8;妹`zdXPvPƤH-@<;B0{TAc=V7O(jÁKu[gw޴MNz:wHFĭ~(ԏةGg=J P&(q ZF֐f';o^ {ͶI ^AUFXj+[<5TW7xcIڱ1P)xmj+>R+*-l%c9z Ilq_O{[tml 1I d01\x0+KsSp5 "7uj3:*$X.P7N@PP)o$U%5It&sB#mT I[iɩlWr- {pkh$Y[)bIԚk0@++VܛAlRpzxmp@3VZiwn5%a%{[& n21V.2b(X g38y`;Sb/]֍B[Iذn*Tݠ9dqYrEy69?Ԃ-x>@a?Zʬ Hv&DKe t+EIeV;Of3mg$%bA1jY-22UՍHu}Z^U[\y5dU21FRFcpU#5Z>ݫvcV鵆 Kp93.o``p3PF-'ܒ~(&-pQVŸּkGOrN:W xpkY\k=43zE[@bH1>H[@g>₝;%I`DyJ:BaNxEPe5)?pPF *s+@ŶݳwMi 4\5=fhŅR0n[v1ȴ.=M-1[-K[]#!S<@tc|6 @3 ĩ"3Ze%rr: zvPG߭S @[3(m}x ?YXE0@=) A;G)lvmNh_JU)U]ؐhea*}H2hT8P}GPKkaA;EtHo %Sectckzxo`+ ojkiޠG^]dC}xӣ)S'kޣMruc[YbAsu,:曒z@ZnB}U-?CD me8V>Gc[4TYq-,z 6ڕSMVr.8??z+pD.?% 䞸XR(&Z`,O# Zd-1>m[kY`Fdf]!Abf8t{V)eP64hZm0TbwoInZDۦ0xc55{ vtkۃrxmQc1Zm=4hHdj3m%v2 ThtB#;V%]o4*?qA#e$8IT<MKUgS`(I9'ڲsNb98X݋T2''&"˶*i4H?ӭƃl2duk+pDԵaaeX.LFRhՄv $'zbkB QbO?j{v`O9ک)6m |Z xP_*[ )@0P&-[ Xq\][(R y L(Vڶ{62ѡ č1<} Zݨ&MTqy ZanQ2WNaGVkCh ''UڿcTq[LuR-R m265\.`qFśbb(@Af9Q#'Z+TG%Rքe&F1X/\}.N ӭ_'ڍo0~V]=kJtRnf*N+bt;-<V1;;qc[tQfʡ>&[w Vum|8;ynk_Arʏl7#QqZ1ޝ6A7c3 ~Uz gP8'Ub*KF19 VØ ESg1XZ*zS J-:-Å% ִ;ErQϰ&xLjct'YcA:M8 $?fze#5r"*ڶ3)$GJYc~zקo-D(P44HW,T;[X{WޣPUXs\+#kuM'k9ۻEJꨊ#'dqxj+"HϹV5/:;W:3T@ZFk9?֣WBMNJdg3_[KKx֏$̊V`5ʵmyH=G5ʺG9:$nQ3чy^၌ug740 #y$h2 zF[\iXOInOJ`kqwJ(;}_ pA(n$wcdkSvcHSM` SڂI2!vcp CNҮ'Iܴ ax橅i \e4 8޶JPH'Y,dOAYcb&u߷\W;˾lZ"inlP %Yjqeghk##U ӓڴ*SOmlTx>e6Q92kPbMfG]U5q06Ԑ RϪZr"޶3CtL4fZ{ ʁ"8j}=Yt-15ǥƂk2$Kck]"(a9 B(*q$XfElu'TbXi#pj[oxpټ~JpXYkڶhR SB0OŻsC %E K28@[ܲNVfDZYvySksQkr=4f^H GJRr@QBI,+5 bzP0hi5wNw,` uH$F mPB3~ ԷI@}!M3AzQ:tG#Ѻoj ?A;Nj6H$qF麄 FI@X'J*j/Ԅ@ⱱIb qD3hՄ/@&Y5nnozh2~& ҈wmVpQ(*j7''#PE[T Z՛)T`J!ya9 b% 2 cTm8c) ~lW21@+Z*C ҤMo2[iw 1" sb> @Ջjmwk\r6"){-j֘k]%ҮZ70Zs}'{TkZX#QۮaTh!wLİR{iiOn =?T@0?jUb^qB1 zؔRgܚ[HbMhit9TS01Aauhެ 9 ԯkMjX?jwQ*'ڡ+sȰ 'X_i%sL|VSXGT%'ʗZpq`c$t(:hk}5Et~# 孰IϽf_US`Z3|=o5۶J[-l8afa$p ߸n-SnY&HֹZ@Ǹ\.x^0Ic+v筯7廖MK^N/G T'\]r:LI6$c&( H5Mݫe5[2.*C MƜm{hЮ) A-<΢zԡy; a {-yf ĕ=qճYYV$M#EGzԠXLЇmpc)5 ̎*)XӵS ihɻ$FLRO*g `܋[֗J8$)a܌-ki C:.+U-lxwgPͼ1#ZOX b']16)ucǠr"Ջօt=*rEe FssIn%Hcei+aZG|Dc&j`mr9^ݪq.)@ IWC#<7U0dLfk3[yQ/5Kv9focjI$ oj+ zYi Z!]9ܱ?pL yf㢻}Rj7t[h$>'>7c|{Ka3OX]<|W.o aCmbH5]d DQ{qQU{Dn1H i<4=m z'H5Cdy$kФk ʂɎ(؍۝hjE1P3׵W2"k+J ', 沵S9lm *\~( QZ.856w?=+YFKANޭ5l/O+ۭdsCkaQ*+BMicDf*Mi7Z78\\+qɬ VH zjeH G W2m[`0̎kB2 r&U1b1<ҹ8s}rG:#RT6`κbCaؚ omKVQb6,IqTʘ <+n[Ր 6hʲvT9<&@U è4lf*vǖ}@ř@7u\ܾ 7㸪L`~*)wb$['#ERR'VTDC+~{B/,B?5B޸0:)6kTBތ`И0j>c ؜i+֘aM%AX{z0o +Aus fh-i].B{h#/Nuua ^z5b2= H/4uXFppH@^,eܳok*0rD]=ͻY^1]LI5֗j @7XA]OZ*CNXPߚ*H#tZa٦V܆=8hGX޶AR֨=gmj\c`MPDHqҍP44۔:P6 &°=n=@v@ernT@D5Ŗ# fUz be9*LQXaڦ2[VH^G~)AmA $J0wfcМ+Yw[Z- 2$*E5;J+d/x ϵuW̋~";H^߹mL`:Wiv` #bȝs^-ka @8URmʀxϽkXX\z{kynᔎZ#Tn/2XrdDă\Nc\H 35ֳ$w\ frj`=Mf,kQWᇨHP})`-ǘDqAeS*y)8Ƞ,),gPF*6ޕRܜگŭXb9z>N ūjPN}YWЖGjM%0ă[kdX{呺n䬜r﬎sK[|Ѽ>zV.9(Tt9X 7MSeJʲhAxQh{:ͮ7K&b[ 8jUcEn#[YZjH]{RV6Wԩ;.UXB\<0ȼOV mϑ5l1G&#F4֑W3B'n+IɩK3QPeyJ7DgAFەw&҄*ț(IoiT=$-B翵H`KGE}[w\0 ŵn*TfJ.!~)h8l {SL}+«֯A'Hj1[}1`+qXFGnhԝcހ­߷Ț 0v>UKrP5VV7Q'T 6G&hZP.zô(PP:@i r' ߥrzsD֜&z o= :)nwgX҉Uը6+m%n&jQեi ee71+UԈŠRqFj-Y@wcHtoL~ե0}@ v$'u:KB(w4{ފ[ݔtMs@wsY؈U}:fڀ#t/[.EݱeYfGy^Uz5r$WO5<#G}m-7$=*U+?qmuO&Z ŒǽmdzKyv CGj@[>‹En ,Z'A\7ŒN8 S4641IrD#2#o=aoxU¸0☝WjV.ʀlV7FxeKKA# [Z7pPNXeƥ: },W\B`5r#~v#i?jJӃM,@ǬWImnX!w(`~ո[:of}'V9ڰtKaT%I4Z- .jf5p=ixR8eb.DĊ"kp*כX69'5N͸<{ PzP LS:۠H=[e3hZmSllj-@  j͖ e ڤty@ڱR͒90 IdCݽnC]kёj Ojֲ9)#ks#n #ڦ8ҥ۾#Oe[8湩k1<ʨ:`ћsCel 4Zs\WfIݐpOSRX [lFzo&H͂Jڰ9 jIE fBTqZs ҂&ý @Z, ~ܷjK~ey'K1IY9b֕P`>z͠&>jV|68DGkB[cpmVZ14ִ_( lP9 +qbpy޹ا+uvfL 0W7H93I5DIں}ᵇ^5PYY TROp@歀]n Lfի>FR v >0g=/m1E.ua3OڱmX,XfȽijt|=/i8SYbͥ0OIdjd(AE`uIν+pՂ0z/y&gJ*#qg=G!")$z ]$v[./ O^[$aUۈֵĶYNӒO'jlYEVLrӏz$o<5W*tfyPXxb‹Ie*'"g;Q B:@ U{RT`z$U.սcO_zH1Qqg%aR,ȢJ'p>ư=6e,>M-aFWvP\dֱxj,zE=qU۷^rOh]cH%|]ށtEDAl``v͑hܐ1W?n>J0$돽}_+[.~NsUYW.Tqڲ[3WbT5ɏO@xl)E`@*u;o)޲'Fc-3>Lfޘ 3کu͸4(.a$ۊ%-Vaڙ;AEhٛzbݥO$tL^^0HtMI[A%IT\ͳD"6Y\ԝnIL"w 6cOoSI#~[0sھrJ +*׈IgP p"jjǝ bk`qm^5pAASSkp=3uiV%[O--;IjmV؉G& 7b>XMLԚPL"cn1 vO4iWwsDn.ITHN֤XKTO$b: qn 'bo[JjO1?zPyPթ+fRsV :[˶ORˆX#vfa2cY):`h}+[;v;,X >׃D_mrqQ,N7zCHCu$D (3-FMְ"qlOZc8KlAls^nk|L~~Xzbj9:\1kY>81l\.Q= +]vOC1XmVgњk. 72+u!LWsJb@" 13V, f#=ƛCk`/pZRJgoɎq]QxfЅ[D@EzGt.^ְc>O A=gW/*ZQW/t;k7A';tQpTv `s"Eime.ܟH t} e'?f-vFyތAb$8dn^3\XuAlE 7|;bdژ&F.w)lNcXǽHm8w'+1D)\7V@4\f`HFe>F w$rk+AkLY̚ofP@Zʧnլ\@CC@)-bII5"iꖴV X]v53[v^SBE.ndQ+kqL$QXZӆ9>Rl*4`xi\~fbŌgP A'J@bldJOh]r|0";~>}MN[oK*{&[BScr~<3zO5H-Qzz sjNo8c!`Q$ VzϵS"Z`dBJ&3RZûvSS3'cpG"XKAFඁh v~iy%B\R@=V5"c,sj=vcS)ԅej.8<~*mݝCEYwC\JW-AVf &Oz 5KVrh+^H6ۆ88<5*@Oozjbw9'#ұ GD18֨ꎞ2y7O7^B x03*NGZrvĘ**#֨JHE`DbMlgg =(5E#$LV`LLZ6P T+6^ވ %̎-.Zޠ 016X1PGDhij-(.:(]v桭M ,jU sTx-r${Pf^/(P?IMQhZ EV͛ЬzSXsiDkEFHĊ-fFT̐6hmzL?hʙlF?5QfHb|XZٶ;'ތ+ YeS!ldtYj[d[#a^jO*;PM|ٻhAk~evf:3ʳjݥi,lQ6dɭ;D@u#7#wRDƕva[)Dn%VT { ;Ej[.2Iމѱ--Qo ]زDOZ_ PiC9I"1 0=TKw耷D$qW#5G}-wvJY5G;]gU9kUxߊ. =C&OڍQ~ҢXw.2rEE/b%qUiظ u緎}GcR*ĴG^=|>6O'uR kTlGĘVv[Ё3\Iކۂ3S-=hZoY9=D`TnRbFZ[`EƏH4햷?Lm`9Ӛۤ-Ŵ9 "$jJ{t:v\]'Q|ԵkaJ*DONk|]q֎ jq4xX7V-;-ăҢꞩV@֘j]e'$au% kS=zV-l*n`Z/w+4Op^j^Qً?p+4f&WY oT7+YZIuH ׽j-^>x܄}.zךASR.inm4Zm "wA@[͙F  0:ZU/љGނ16I(m mɸ`?B?e}q5;:ۖy ֪#Vjlݶ@F-Z/qfW1yYIQD]Fgs5Zj5-o'V߸]HDZPA۸Buv c n0?n^dIH,>Ҩ nƚ9YsLv1/K )U&=n^*ܣ +`XmZLl#ީq@_j?^he} ?Bkf,IP[}Q\r^% @RqIpjڊ835 {v_%iCWn=17YL0:}X V?j+)ߥhd}p Fk[iGkhp h%l60j+n~TA QQ#ha{PO. rd]"Zvm*"g>p3[ 'ڴMA3L͋N <, 3]H8h+ W\Tkp6YI3CpM帪VPv#9#jzYNU˺H m2ZvzW*`34*X&@Y]KgOҬ[!s?@D5-YZXVɪjً]NSBu-+1;d'Y^.Vnkz3fkqSU2x7Y{b> fxwgiQ6Z@Zgtvu=Rk6T>H"3Dv@"ߒ .BxmbX9I6WV: k8=Vu}H`ҘhVcMkS947ZA@ &St8bNrg:Q(m'[JX 7IDʃ E$0PVaҌՍ&m Kg1ZϤTvvxOѮߊxV7r0^WA3?4RPgkV8m $+udyҧp䓊tބNEEnNGJdf&?FӲhۙ=}4- \+Ciؖ,W"OVc@b SWն]%6vIy5P r f;W!U2 sE-R[sMKii8~$];\jw-yDO_~.ywn="=4I SaX"ڇ*Pp;-EƸU `)XՂ'#ś)khzDGЈj6CuیVaA,dOޱ!*35[7 A#,@8!Z= vѦQ#q&>($"z!; IϿjaX*02l-Qp A:O ! L 4>]NB[q鑙0.R6P VVbw,#E#0cbb j\eI?ps@gDz԰ JZggA4&'O mIފL @%E]L;v81XC?BvȠ*DuKn.rX);dxF/=nHA\m+hUJL!sDO9r>Mba8̚ k@ Z}E 0:D꾡 (Sp =h>in1+>KB-0Q:P`gR+A6D.jۆ&GQFm9lb}[EnKzaT [ >IHFlOP0K Yk\ fZrI+_L߽!#q wꋖ=cr~܅v8VbAjq)1F,yp1駼ըu.Tw$P%;v0h$ V+jJdz@UrA9}3p+Zt{r'qKVlYXu,ܙ@-PK p>ˆIc޳Fs[iᦀ[ns4VF)1k"{֩:;=TWHW.j\U 0OW.8o'#۹3^'?oo\.J?\]Mr`p=@GpUXjNx _ִOi*1z&LG:{^XO܌P֐kaQI\qpn a֩64L=B\ČsӞuϫY>G>77*@~ǟ޺oUB'f"u*Aj-%!v/M]—ʶӏ֦jB A{V2V 0.ww6[kukoRHV3V`a[sYڤjZ==umuRLYjj[֑hc,Is4l+Us.[>]em2#4/!)OZj@E9 1Uk `%"$t qA>1]Wp8(g rAP{dGa@XvpF{kKyABoj-emml>*c$*\DgqjUP ֌?ir(A*FGuRrB0cc{PnV[g G&h0Pr9eE-DtՋqj7O0O&GQ[MFfyZJehZ2EeYؤO1b̓ f+M #qE-[р]!1 "t֌vޡIQb~MbuXzAqMl keVҒ2?+50jپDOv麻w)(&ukQѸsQ@#`\PDcdQQ[<0FӶFZ=?i$yxNC`H?g{ip+ucxmcq.Q\lv]X ;GJ]eU cpT(q4ZO܇lH2aňb(2[C و զ !&IFGz!@1KbP{I# []'ҵ,5PGtbBC-Ȫ|A@ m4[jN i 'P%s<hZq|m5rM}.m=~LVDhO:ݽ5ʺd&>R0@AT!ӏN3L֕LtVBFs`ZrCzc[Nl奤H ``IeZ3115ыۥ'#UV-cۧ7@pٰMkAk͢6nފH1Fb=HSᱴOHD_Q v`09犁SY~aǽq\^m&k7J0Pfxa[cZT{od_6廛XJ h3׵Bho. ,Z7BGRf}tXE6ɂ?oKKդdŅm< V*^]ۍU4+tNRrj MF9悮4g߸mOڽU6SlV?iN[ #-Vct&Jj,/ [ 䎝:AQ!/FbmI`%s|_I"I40->Yhbip'4E /nXEfSi^Iqe CfL*f bvGf@۽֕:_U`g+IF5J ~M>%H5X]w.ɧU D1}Zw 9ȴ*GLk 鴖t5*Tr+ WOV=dž&vQ;P3j3|[7%Mw^c_#Ivww' Cg+T JLRck-.QvT5:!10k<_\Ϊġ㘹oabέMM@ F;7 k5='?sYDA ?E"ܱaBm#>(Pm!0s5nczP`z抌+]h m[6$ ::MVTU=WգTkn`Wŏ~M$mv뒠ČV؜RjH3 s6.-XڻÞf3_.׿[kM ޣaj\L\زH' X@rFzQ&sq*TLH%q+7ĺ dAZJJw q-$PUMQzr(n˓UA;Iu/LnvŻ@Q'籭foT!hCn C[-9t9$P:۹nWFA7 6/ qA{Rv 2b89Ҹ̖vs`h ɃEm_vSdG_jn[-;.c#) [ɀLEpfZ tUlOz N0nd~h.U`Lh'G3A-A#űl#w9Q \ hO4zP,EƗ',8)&OXYBltQ9'悻+h[msbNXJK:ыdDЎ n?l1޷ &jbFNnc=o p#'™DLcT#,ڌSViP@KJ:alA\b)ERp+1?3StmNjA좢oZhUu7Q#$tYk/+^[HѲ7Hm/oLצk0\vUz֊z GSӊ)عp^DH8cTw1n.^KVmOdX,jJcnzWQx02:[4@*7 Է]v>aNE-^1-[=*LY]B4TVX2KWxåՀ#kq3Ϥԙl;;c1YśWH1uRز.;d5]K⦊Nl8˥2|Om[wr ckc O\;YJP 9:yH0[_pOvݴ.c1R6 -\HZ4aDǴWxE7A=I8{5;*7P޷7iKRA7$玹#]Tk$3cx\bׅ[2+>,qɩBTJI5i `8fׇw]Td4mkQյ L@$U`'bc޷H[t"3kP5Ulhqk(.T>|nT,m*ٽgLSN(t(aD0WoeԫL.ZC~kM9\0 D Kd*b@&!{LpRF_sB-Y\}I T45u"BwK$QC&8TASU[MŢmQ*WUEMls!\vS?s\\W_.Ǔ$b}5 p=zEN-G`w֘\zbOM4l``NynYlTH-.@i۬EC+u-F9RWIQ˔ :Pe@T,\m-0Z\cVSR0-VmVz7^U37wȞCI*#iݤzgEcbz0k4ԶfmQ֬f=pr=(N} H$d嫞v=+8^4f=?vm28>3tB-!y+ڰeU9_h|?v3=EruՁPzZ,ڢEo1\@F$UP3׵J`m2u$=1(#q[F=k[L3TO ?4j6ԀG?jج8J &'HSP uX"nD1DrrJaXIѩO*\oQAnX5Bh$ $pHTMYݴ?=˭zFz\7sIm xP3}ղ2rnC5w'pp'v}w,"x?fUqL1 m8բjBf  mbFA3}\GKENF@ih`j0+mjZj,oa։j-hȎ823ST[+'k1AO#j +Ar}Kj㢲[6 UPMuQ?m.5˯H.넖ugѭݒ3>湬KP*U]c0k.CޥyQa"В'u9ipnux12ՆZe$ӎ>bk|35iս>#l]+loul?jDi%Z1~- &$ *n* @<-E!ZsX\&a8vdgvMݖk +7W_-LGn5M5)@<1);UǗ،Nq*%ipFe X\2 >X:ɕVL%0=J7 rphś:tLhEm# FMw["뇅?aDMUO`(,[gTv @LQ-廓eʘCKI l5 Sm¬06bZ@TY 'U¾Ҙm<ęĻOL!r[Tסe6ݻʎyW!N om~jhtxVZvv uu?[iZvsF<|nV{.[P|_Cqn'1*-\dxY.\%UG^5Zx+vnCQWmq":b^1r\pMbVclvS%[ta!#xd 7ELu!Wlr~?b}r[qJ*uSޅQ6 e]$n_ vgf1kg5شN+o^?AM}v}O|5m`pؐg?q+śIlsKLcxk'9\~fKzFNMy|Ξ8ts%xW^ۡ[uIT jfǕmPUF&GH"9 ˯}.1!\p!d]ylFrk1sKfXU0\9i-g- R&~޷BMive zҩ$҇b#hsT}@2NG@j ޤEKfYHނw F#ۿ悥_iqP4lZaf9$Mʡfq'<еmn@( 7aB"Lq4? =?DZ~fYB9$;1SP`D?4UzPkl-dְerxb!JwO-;Z.I0h[Pc #ՍansXcb2#Q+zMJj×pLL۩m n%)rUĨgTrԳڤ?N YC 58`oh2D 陉MP {H:dQ*MPծ巐`ɠ秜pm b8?H:x!+ww7NY.(z nYekf?K7o2_vmz*KnIN5*jGiI11AghYR-nu,$<(3d12N`F`۹z3'OZ&ŝFݹ=g#~xz>׹ڌ~j+ix=`Meګwmv[=B q 佹I8Vz>f79 nFe^BΛAۛ`8BVl lTZǴѕ6y O_9 ڽnы̓$GS@l_km u,ݳ O&nkmI3FԱ ANY$guJͺJ KMgWvEUj^kFyAOP@iQ뮳Ij{CI'8V^;p.[6ؓY]QѦxOF)oi.)r"vA[{4H\Gbq͸NMY1@<]gW߇x9{#nlݹj܁rq'sQj ī矚x{LX%g YRx&[}&-\ Xyc+#Tb}|,Ϧ_3.&`M+EMJ8p5΋)&V(ΧQei# kB}۔xf/u(~YZ_,$<ԭҫz6,[[nj(@&[iHe ryP8EwJvԵۺ]PA)" cBQk4OekGCRClY3y1=F(2kBM)MJ0WAͲgԟZԳ`np .AUEnHhڋJʛ=3j}N]$7S++1ҲTsR/TYO5)_;So3{WTܸ4n>+ #1tVm;d 鑋 X43[81}1r˪)"dD UJIi:޿e7ʹ[/|6Ԕ&>+u& DIJNޞ2'>Ճn{ ~hmA[C[SL}C=\%4I5"Ҭ!ާY=h1bz)6k+cSJZ t1Ӛ6DmrŻV([ XT+Ijػ`tQ&[p '=澯ƿovo܀:\u?=[o-0IU9қc;ve]+;۴ Ø'=u׍NDٮnmI L7^"tGc{KF{҂H=0=l1eVIP5UǎkTˋ|W.1:}A9Vb ĚRm-]=Ԯ_O3NׁRF{ч6sFh/xH%;,'{I-t%*ȸI{Xr֠dqtdSi#޷Y۾ `vTĆX wGJkeYo*i!WaIl{Wp*gѨqf?`#GHXTA$wR1VaZ`7XM݇rC O ҁi2BvݺT]$B8kP.J5U1>F;Wd?^n_7,r55ԴQG+SKb/Y(Wk@ɠ"uJ&aԨ[ynʶ1/#uWʛ۵q̨e/q\;D^*.D6H<4cxza!@m4N# @0{C0|$OttsB5j±q4fsnvֺ"NjZkn*cjbk;$g41Yq7nQD1zɳw0T7*uU$Ǵ)7Cn.3(UdJ^ژ4RVC)xq6ٓVXMwNmfe.w*_Q@&0zV-%in\&>'v;mcaӶ!GvDFt"{OF~fZzh |}!FTP:$Vc%[v0?[,Q^o#>V4BrI?P؅WP^ ~+u/W5Qs3.Zߜɞ+\EnJm љlM!c$ ;d`Q&[#(ű#iPjpDG mT)BIPY(FFφq}|UIaW>:Ga&C8z~/_;ʷjΕn$pc\[u6ҺKLEm["˨wncIڦ&(A!##=8mF+i%IO^{OeCI$ZyG X#sSrX G☄1v۬I89W #SkWny"+ Lj-CL5q[O^R@,UT -'Wސc=<Kw zO̮֨3Di,Y0(OzFRWb(qHizT /5R=x4х w%lPŔ6j]!ԓj,f`*așolfV34EcA WHXQ?,H^bK[U( ڀOp#4Y<na ޟzhY @O$1G3ޚ]FLӊ-~ n+-ۭl(YUD inm.NAl B1a1'H:T}Xu5JnbHn ѽG۶]rnQ?QPMnJО?VZ>'iMZ%'0b'Ż^ 4ɺ c |8"(*޼tlEEm:Oj5+dU+i^[?>Ŭ[]Fgf  ӛcEuHEh65ʖo=~B̎cކ4 H5yuu3D~k(KzEZYkMG`rjpogUA h:{Kr´#'=jl4b5 +9= I*PjW,Ikn MfO 7S9jG  OZ*QNm M\߸,J,z+Ƶ-0Lqk.3XXH3 [ I9dT5v;`]cMi8(4IDm5%/ &ٟ\BFLW{b1Z%畆>zf>eW,wN(ZJ6ŭ:qFVZ m鉡:!13k|o'uz`}`诩9?(&gή00MC ތN\?tw`\cզ>< ` \+l =#\VVIR^}KFNsr㤚\d,=34m\mJ#qчV\.dvP\3=%cѩ`%TtH#@,;P3eM k**Օ[U4fחy I4GE2ޫɮxvA=Z.P̜h҇2 HͿl,X&k_K-ﶬmHSsjs&7A?Z۵LfP`6~,۷kDFbRm2w?sU#]ds(͠H n/s_b ZP}V,&cf#}T Ռ A  VfOCl@DҲWR=ƼB͝ #kq=m}ci\\|aw=*Xԇs\;7S3 ;V*rN1"H61Y$vE`Tk B aҨn=..up-}p d0-0m"LJ,^**y+jiag&qAc u `KI{rUD@80i]7vdַ0V2OYc-+;Z3!CۼUn€ 407S/ E!g~|ǁYA:KU<ǰ=DXVGnw-[j I@t45c0z [[FGJT:Kޥ m 'FwP_OA;R1JA[roS[?H \mKסޱmNy b4(Y3څEJzF`nYel"Dᮛ Ǿ+>RΟ[hEgR[ 5"Xy*p#Aau)j nu;..Tk;QK@+1oa&._m1*$D9MZk1 ^:zPEֹkŌbE ]UHU Xqs5io@jH4Af bb2sDZrʢO<чx[ +5k-a˘*с2!D{O4p#ƠG6@ gfK=okzrX|Qh IhoPrHA==֖=R54]ڱ$ձf1bA12[RK#nf.n"& ŭB6%GZ*xR+#JYݴ ݃X-fv1eC1je?;~+qY ]* SW8&OI/[V'y=FHYbJ y, =j޲F@n6]qELr{ 1-6.>c#a|jv?چ,])POxHZ [wu-2IȭlcVuKqTLNfJBaZߙ'i6vǴԊ7il?֌2m5G 4a]g}cPْՒGCF!6U sVƅ:1!֨?<[t+R-եy϶j(l<.yuPF>S'Qq$1Pcn{xb:tm]۸KA.w o l] sXhaVUmK> ?LENgw=$ȌVbV1P}0Q45Au8D$EV(vӦw' 36:u"sr,p(}Q)V q*gQ&[Z:bWտ] PfĻkkfߛm(S?oOi \t/pkNpj *#Ȯ2Br$?5ƻFЂ:w*IqXNAK1OJ֏i[;< FـHMXP61n{PyjLzĸeV ֲҶT900b<4bP}SgV2腄+Ilf,@7N*Vcamp2Hkd1 H k]G2(-.%QTDcZ -$LU&[klMNʃԤ]E3Z>ڠ ?⭄%IPmܱLN.AU['Vd,μcn6'c#,G=&5U-\).F l9džEs21׿4ljqrPS(wwPE|QZRn\w1EZ.)wG`$,Tfy5$mQhȬnmSlI`Z[+?Ĵz@5ºcRyм-~kRJ3P  DQČeLhth {Q65#q^Q"0MP _4PtR8F`i'C:Xb$8U6=&)EռAi, }#n Ou@^ nz][=Q7E' Uh?no @5hBj}ղ΃tnN4?Q7 sH']%CJߎp2$_H_k4vϊ3^!cu88Ӱ')䚚ջ2/ޞ\ƞLOJLj*X8sR<Gڡc-h(&>@aXH Qpкh#V+\o>*YuZ`bY HXȊk:+lUʚxٶ bI*Wvgj}=!`ڷU*nV] 6qY)"˄I=@p`bc{ jU#˾񗵧\N{Ǹ5+m=]띮!^9Fp9+ oy#UkTf'h}4 3r}%UA "G"R{cmۉY04\jj4mea&)~/M-WN|w>h]mC#z^<^o':#^Ǘ76'D3fZX0 Mrך@VfWǢ1[Tw沪3ysWDA5i!XSM (H< S*Թ2b# cɡD UkHL{S@@$R}<=Xy4țF5H/ZRsuxEUfAs#-=;kSjvxS_;|X~Ҁ8$}дp0*R!({F ޘR: ~kR #ºF%-ߊ [ivNDMF@,6Ӝ{tjlvQ 2{G Jez2Ͼ $@Ap'3ZʚjT[+tDn+$ހ$+h-=Vɢq<e|tԌwZŹ?nZ_lۏWC&YW-Za\`b]lou8Vy|x2f#>) uv?斱T@ 郧mqRzƖPIb:8C6'n o.%G~,xoAڱj{QOT2H_ZA9,~j4+MG_NՈ x=*XvV*18imyU2Ǝ1f$MTc[BqYև>#kKhu9??V'K:n1tTUǓUaqv9$Zj܇EuZn3zW'F-ֹS ~oM x۳t7BQCiIe|Qn2{vBzcO fYMp-JV[PXHȞn\0VڱC܊l6Uٶ)uSRΈ]U^:IgN\X?_w/7S6H{yKYyRnR⍊5@[GsADGP6tW^ݛWײC[!~-uyZڽn[Wѭxxڌ)x=;Q\-r: m RDoPzI'$+nG" ڍ {yrz*b:r̞3F*[m=  8gaGz3.Z ҍ%0:u*#$0S,A$P\K,wZ"1:(qJ'}uIp -$̘)57- ϿJq;Nlۜyt;ʖ2$ UJpz\[,ӟ*|nMT~J3F JIMylO>ZPn=Vv rI4dl}zH?>mĒⲈ. <&rsр[vp-ߵ m/ups[OvsynI^Gd5nڱRX?qq -m/P&5v@n u5XuHY'5-U}H`CosMb+oB[i؎j {*Z9Ps V6B x 囀ș#ۻqiO4B a4kI|Qtށ*q4lj0c ovсZbn>rb} K.e˛f*Κ[Z˨mڙR^`Ճ3k$+pn5m}sRoQ#^Ł+wp Zvv D)wpe=jеm[0n=ˊUꘞٶ?"h wz+sH"(W=wb& ˅Jz |Vb-S1JՅO%k+ql[ժ;D ؅ވN$o꼽S?oKDң[ ws=j[K]3:$@OZ7T ~jp[iP0Yn3厧P(w%޿*k ׄKBeYOS">)UR1Mqrj4ZFgk>ء]pP(ڛTH3h, 0?2>l\@jH#"j\d&Gq):޶үQZNiu6 5Xj#z$[i5[DO7읬 kFbDѕfڲ.aϵzoeP9m( o#s#"D\*;+HF]"YW5]kԧo>Qq%u=>aFPr^bI+Aa0zB?etvA\άLv)fjo[ش `wcWì*3[6nyGPD)b-ČdURڲrM\MO)˾bTM>@6:@ \եB W,5 Qtfpp=W"ڃqCq!xYf.*]f8%jZA}SkM9[ l!OA'ʩu`GPkR5Wk4Xָ b]  1⥱M4|-N>(48vmZ.u J5t`Dl;T@F4HYEꓪO@j+uECJmO5 ÐARcpܵԖPJn4VX);1Ҧ+K 5ή2ElW ZIg }ܴI(mJf.540iF(]%`4|2ډKvwhF|mF FF/eyAKQii8ӱ0gBA 6ͤAԄAք.m hVrzJ2<\u(VʻF6Lm_[^~z'Ң!rJ8iPGlv8"H \SVq{msuZ{dp# LOwXPL4" F('!YKlCF v|1SÃ&x]#*D:UDeGqZ rŦ$sU=PvsI;lP6q=4rB99 "q0Kz[zT#Mm겘-=u+ﵺ'nHŝ=` $54,Ƕbz^/P:q8A-nF.ŲZfgmQ"֘۵t>(э Yo0wO@B5׹]tĀyV oWamպ'oWf JTʹkmݹ f3S{zm[R Ֆ_fή .Sˀ1oTRØ'W۬Mg?s+џmS S'>&;M o; bՑ$'cYohSK6aV$Gܡ P$/;won~+uu;ήpbZ-\ }GU߅ipZ:wW5A^HھO_{eÂ@޾CX쬏皊VXX\W:M͞pvZ9Ey;^&3&Gy^p="7 h0*W cDq ZҧmC!K:PDvOR;2õ@^d0s4RlqIqh%vy8=h` qgqN {ګHv''VNc'Z:}I(mAf'9{mN5_P0{ցU ~jm*W3MCFR,J;PUMe_SwiVY[[7 OHl0x>5.\m`OLQ*o @ TBާ $h`cNp'h׭Annș=U_ߟ]eP с%.dP=lnop4*@33"NKc *|P1}x4.Ye(_hyU6x SLZNOa8㔔\n9Vwe [q+ji[ nD/?ڹm܀ߧ0GPtBM,Y]K0zCqK&IM~i X-?#׭W,ܶ<}XZ#TcFo9N\|VƋ iw*X^!mPYOYV'Qi,FvsYF*H[TgQ {Q5aAQы4EFhӁxA$u>p?II4C/_!YFnUkg5-ZkʐߵeluIFhRQmzR7o^0{[im%rfAЪm 'i]/YXѐn}- zk~Xp=kBǶ~LI=~?n:Ti=Z̻ ߚk$4T;TցpH+9aYctKmR WSDj;zX_e擸ekP;:w0ղdt&Lj?.N(,qəl>!b昄O xV`葴 Lȗub] qdq۶y9H:[i5`Vu #'D:O#z VZ F@2>(-m CEairIcf)>At,ꋠ#57SqD :W:ZRfYVNi!*)˦e CFr"q5k`Ϳt3mZ-8 L"Ŵ+ FcNMֆ%""fdrķPkwFSRɺaUI$Ѹ%ޕ;L8?4\e4bVX)*`]D DW,9+)c''-F1CDBm-B9+dUı8(;[@=z^@-,δtڒFx1҈ǧ}/Kn:XA&yt)0G޿G?6oknUr7,)|Weejm'W)n>NF}:z`2dP\Q5-D?5nNӈ:5#}0Ć:ēځ(n\}HLo+3$QOޑjpI5M}fclM=Ұ=4͟~h ؽ`0kn岁X7#⩸"ZhmH_ޅ6wۙ9Ess.G꓉ZF,cǽаۏG!c89,B'<I!{r#m 9AeB2VC[7<1f[8iZKViF>Fjk8$H\V+b^\VXu;?Tn,ٸck`zZ}Ee@$+<|]bk( u'~XMpz_* gYH+NC0*-="oF3AKTtBxKp%ѭ酠[h7XjWY]Aj[t 3.py m^Nr1Y;Kmo((85#lbbZcdIg\(z Z2){vFo\vI󚕅q $x55qa70ž9ZV.}]-׺ҷEp!fa~i-aKi9MxHnvY,8[;9bDC}, ŇmjN1=( V`mbd(RuJ45JZbVb(sfsMJƳɰDcl P֙m1ok]ܴ 0@ѸwJQWt35-LGj`]ڧ=9%wu!"X- TV$ю@Aqe=fUG}рu۲&3Af҈bd@{BHڳ[oHޣZ5[ S \P&HMn+\YkLĘ?ZVI yl,۾#*^Md bg35:e10zn\$Hf yw$UAf>AcֲqLgj0 5Ik* 4Vu{%]vPVQT{VQ9w?B'XحR#N "q G+-\0:W&=\,=qne]h[nOf# Vw3MAa4L',XP?Q ;7ŒϾ( ڗ[(Qyc=*v ;S {7msInVTP 'KҾ`Am1+o4X*n '|Zy<\u8)q.0G&1O_1fZe!W|d5BG5lc0đ\ #bD!Y {W̔{#$aLUTȓ40(uLil/*}j BāVP T*:ɣ0ާU?ZS $gvn7&ΤL|e!aD.hXMY:l :+j*u֫X "X*+3hĭ4EN֯ ]k+C'޸=DރDjp}ʚ]$4aсI .qPCoLr[јwՔ8CtV\T"چ!suU ^ss%}ۚw1q[){{+Ze[dhu>4;92yMgf7>Qqyb?WOpK soTs}XOj(5eV{a; 'Z]=^ݭO9B @rsMvo_N}y3ELW|/鑬׾[C/a^מEwsv]f1ޢ-RҮ*kQFVWgv ~3'u葉,As sȩ qAbjRr@Ѽ-5q4 ͼk{ST[,"=LtkP@V-%=9k;5*eJ)@XM` vAbyD&kdlWԛBPP`5;qOcѧDPI{Qڅed{P4P5Ñb a)#A]@'ށ.r&?z xXבA`(RHѸp1Cz13tyAhJƦN==h ݭ;:Z[ѡZDbRk l ^:}akW뻬FDVY{[sy`҃(s{6ťC|%3yEW,x9hWg`y?jZU(6En{wf4("AڰUr2OPR-zT=ri Z[Gipg9)nv _ t$IaD#-3BDd(ѮQAɪRcG?4K˂ *x.ilVwnhnOuI0 Vm܊` {Ѻ~ҋ3UYd6'q=(-\d沷'rThl Km#Vo0)=}@Z]bq&m{(i.:S(#ֆ{+AwOp/kA= _{{ _1oIb0sXRw#sU JnO5+.f*5h+|P |'β}:^Mok!f@]qZ ʁ=$U+djmlqNjaAoJ'P8?5kjfjZ.&@Y N-*@56O6'=.[t%Xs '3a0"d(7OPXmps:fk|&Y7䆀I]$c"ĵd#kE.ҍsީe Pq&Dkd.ߏ֪:U  &[M/anes kdi@Ŷыj>zξ )n`+n03 #q%pA"`cu5v[bJZJmf9HjK(3`mzYCmZaNB4e'扇2j6PNM cw=N2:PXpZ? *9DOAFT@I"0YcR}`cRs#2(tyè AD9;@ggNSDV2?Qk*( (bew\S-^sq?vsgN6OzWh-pzUѝv55f!BuXAShbQD }d{T\R3W@{&ڒ'3@K}BAB,*mib@&=ⓒ<u= l^'ةWVOW\U"$xܕ#hn[.a 4><сzE Iqq`PwKđ+LJ,c~)ĭ ($I%0ڋn jķ$̞bT&oq]%F K$#"Һ%wdhkvnRa4R]bs -}76Gy>y_o94^hȖBq"PJY勁=Sɠ%[kd"ǨRرiZN:%ç_.#QVnQ$?1\l1TV$&98kk}N>+d49--'0fCIS=T-jVLzA15bt= ~N!dm$~آOHbk{m@e=EY$A t*q:BARDkH)3@4TD@)b2ÞX*ݿR)e MSESWi5?@ LcR{ D# ]uqڤwn1R1CWC5pr "fn;pNs RSb<*O3YFHzkdF@hcq=Pۋ{щ35  \9zSLUm˓Z*Ř I#Fb&0P8xqboj؋{ʈN*ZZd F]/Z61pxI#:ֲ{" 1k~BΰYwZ,:`Fq񹓗m f}<}yoW>iڊQi96bpx'$|Ey<ǧڭj́A']=3 ӷpw~zW*:nd4,%ɠgˀenk#Cؤyj=fZvLEk0 Cbڌl[$YEr$}0H*im`$@ie,xQϪAF \@^[UǷe`{`ԑTtTu1-y"µPi@o Rz1@wDOSf/RUyF6ld74.|8@X6`bh4ʧ_ycֱ-Ew!B +~b(Z`շmB;55 ȱ1R,-j # 3f|m?qFZ V`ɬZMfI֘@ؐpH5Jпm8%-,2b0G PWGhlhn+ersY`EdW0ǂ?Z4ڀ)imiܻG@<ٷ=~ԭ;;%<ԋ8&j߱_PQflizԦ4n=E*r@9=+(K8 iZWrjLs@;KŏY<!@V;y;g?ޥ>w "15TIFcxV$}>Vp-7U܂b:֕khK`DѠݿoJfOWqc: Zw{4K5}vn6"/~$U[F$6&wT\?l7"Dj1o;MR^!:ӸՁkp2jL .g4i^w?P?aUx2sVȝCk/xi*˖< f[ ]=J'fdwv257Shw3;@3)իշx{m'4UZw,CSzE`3Uձr"Okc(:vOzW1 KnYf,/ZhBjk#o~>jܽlSf!kdZMQh@>'zдMWCAoekc湫Y܍pNܹgjBF[Uth< [m\"YDQ#Pft4TU %Ѩݾ#}'~\Tr*ڔ8Wg:‘ .mV}lT:A-<hjmQ[* .h -HS9J*f@7`z{2"n)>Z#@~tFuZ".a idZ A"Z뀤G/h%p d)!V;@{v=9kb.کMM%G40WrK1]Ti uw"6g$nciT:׸F@-ٴA)FWHQZEf3&۞$ Ĝ+Jm-xbtY7t,k8ڼ: q_#ushVZ zT- U۶*TtP\cV$ST+D"d h?޷X"[>5)5@S?zH2dR a05 q[ jvIFCj$KǤ M-au7WsF5D׶(n4  ~7Ix:`+/tuX͘f XMXB g4!W@;g J5?4b%s{w<7rg3U +Xۏqi' Ԓk4HȴJ-En`ݺ|P%;.bqqEEm:4)ֈRBN Xt 5GK3ílO^$>YZs%h#,-{JN0tU 6αoһ[dt&㒼q_ZдF%AF}W FA(#rã5FOQr $~)5b.Fe`@AHwsВк =7P qzSL gְRWrP[E-⵺P,=F[rA&IAւme3\fqf,$Qt*,U+[  z1{vW,1@ګB5ZiIX in0&([4L?̓]Wh$)1tNn1HKlH,5 Vo% 'kp_g ̎ҵR;[b#MVds鿙ޙ+aYہ9_VSQ!UX鞢:]P6bR֝y!x&yTփOS1+`,56)kt  X)=pZbh__xP0i7VWs P=ղ]Ut=Gԥn$Bu3wze&@Tge$pO^kYEMIkfmmgjXC,ǚ7bJ8 T6Do;]q`HQW5G; UkLP 'Z5v*_WI!ڼ~e ޹ J@UK+T[} 4f mÛ4TY$,qցN7PA]ϷMEl3*$7KSnY`[d(I;ՋVn5Czy&20r1U `tB`o:IGJ֧sNzr~4 헽(%zX~B( Z85Em]'0a۸QH4Ңߩu)ZqFGaYm 5bPH3L9o`FjEkQ<Ry47#kWm* Z麹}z[JǁX,1ۘ4Z.CȬk. AT0*T+\ QYc:&88=*jQbaUih0A'E>d֘ERlߙ楲u:}&7HU$݅fZ\fLqZ/u=mT F?5Q ZM85ۍ!ҤY'*h*xk;S[`žT(>u '4Bg-pI3U~R: g(^TA Hh `X62u֧;E)iAl4VtΒ% wl;Z*ՆbHQԨIR-VnLLP?V$p{Ru q ɁR:&VfL bB5B֔l@J.$b2+"1F5Y콢fx)ߵr+@[l j[ncgShw5*Iig|tvdS\Qm䓚cj]z66RAtwR845 f&x$]] !7Ϥ1hWG2+d#'VE_pXVCv[Fb rLbm0ҷfv"◞O|Vyt[?u8=ↈ;oh}S;Vi#e= s7+(71n! dc$`ׇ3*֊SY?ǽe7?^ns9q6Z Wk+-pIA?GNr 穨 buLSQT  ފZVH,`QSۥc5;ejŋdU.0+y0+&08a3[ϵTIB+i`n8<T Aҍ= pM%Z-zL3qKsT6&c>xLF}k_>~rhڳqcZNn縮UqX9kӬcL *y^zWΡm!dqPqV腱l<Do=ǹ@fbe 3JW.rMA$4e;GGs!79aQ$S+)L+A=&nݏtBbY S@z{[V t;}&2N>jkj6ЊLw#0 `pZ}B+A2ÐjӨ%XVH l w;g_ I)IV'CoҰF簮[9AcOjvܞU9MC`/$U5ڡVIVA"f 1h,6 a0عނwR@hMV Qw%zTl^,zӰ+dqF˛l˞wX$pLܽ .*H]EEmNݶ ^n"ɮ ЮA-ITV\ FFR5HR>X{@jHb\n#:V4[HϽX*\rzNQ2JSX`ơh?lFS,C,Ҁ`;<" /(ʊ m=*2h=3F ||?LޤR<9'MeOY"+Yͦv(v+TM-Ȗ5omPs+1[L]IVC `Df(E x[7Z77r& N0 uI9bZ63) 'NO(OF:G3Aw A#oVV,`k*VU3p5Ӳ]$$rL稪JdXVmiIm45bV b+YGIVV471]b?]NxK`.ۛo5K%F"S7;H={חu[Q(sUj]}n{tY-ulEܰH^N޾9`j%ĒJuJ'5ºDŶ֍̓2"|U1.LP{:0 @ڏ'PI*llVTv*OQ5E4dT{>snW3 ];?֪6PARs#bM7KiR+J(dA4AFg3ނ ʗm1?hwm\ *yK AhT~՘$h*XUI+1oi@y צGH%|U3ضd<@bm9[9+s+˲pߧtJ:{'Zk62YVP?)nNfj[ T g&X}XsU7A#ȧz[JH7YbŴO-/,Sژ5Z>2:Q@R B]qVt_Ka6.< Hr(k(e}(ZUJ[%*?-0+U|$n皀`q ڀaz ڸ\ӱ$gނɷm+1QKPn[xrH/X{޴V_n|UaJN*mюҥ?Zհv'4EJ1rMeU1@<Zcn'Ln#ShKYW@2+E2Wd^feTP h\]B\k N6 #?Nѓ8Ċ lJDBĎjkpP$mhک)[ -9%WIQ#q߁Ҩ6 :Q݁zҘQ&@ڪMTR\9j@o01g) T~ՕThޢ1j. 1\DQzS[VgPEkjD^,@¶ 2gYAwڍFտ-ϽCm71z%cIuP" bzVhČX!sLnzyr8eMf,5nl ɭ|?r6F~?4jz]+HF`qzm1zV r B[ p j#NŐ->c{V2iTNO QkzlW.C! dsMnr]P8,k۩@WB˰@ +B)6VZmM m#ш7 m׭f(K-֥f볕`gsFV;N#4U4jٖqSawGzcd~Iџc")1&h";tzׂj$+FU`03ťXcjb*.Nh`7Wi۸VVUY'5E\Vڍb1 zF& >Y9"Ghm Nqޘ;:#EDDX }T$)!`zpSE6-Z0wuW 䞔fN3֥Vl$zVQ Ddv>MuB0jGD/08VEJSew18a .WInngCLI *jOEs1[\sRFsHe8=S5U Ȏ(dhS*{hSj)ɮArՋVIfz7V:;ϴEv$J϶6\.jؕ)oۉksrn77)&_BrŽyLGE;A4m=4\88M 9#1U 浂=qnv4q\ǀr++BmˆH3jE\+azPB)_`Qq;_2I*d m0GAA)b“h+0H*4[{vH x&hd1 |+w<&!H1#\Q!1ƋbϞD,rZ Py$g6 c«2>O\։j\wǿsF{rպjCAwL(Ks%O楫cKi  K5 i x\R(+SwV#Ku9^jʃa'!NwM\]4j3߁(5@+`ul-a튺@mUX$#"ѕ¸[|ұEB27G^€f nJMcSr>xj6, rغsjc-  *s_SV1F~sO]@,m1ȚNXv>ձ:K3^oZI;hZ_wiGj r9U!o5%Ͻz0:(CYCYYyE%ZdTW%f$+T#Roh",(a5^[|Kj@$3ڳY荴W 5RMD)hʛ@H5vz v50JAp *;KhIlVӡXѷm5}~)[؋!g:2YFfI"yP7HٖԫܼͪU`@PrQդQGX<WX+5-CPn]VM,0M;1e@< PV}&K'#UG:>eWuSAhs dbM[[#ڂW(}z5%Xahɪ2ۼG53FKmzRY#ⵑED#Iqbh\U#XE@Ě6rO2mI $:9qXj,Bzcq;«n3qyuJw~eW;f`DXuX 湴;~a@ L<)rŦ[Ms3UVZ HVn'z3C l0{њeI,@d}=R[9N Om1&LlkOCFqsQ;:$~JMt]"{Or(u PV`o1sҤ\RG\I mda銐TPe{N~QiJ}LV)w.h.9 fֻᶭ۵m% & >)gj6tF@0&ig hK2)6n*e8洐+oD,x?ip';`J樋@c"p'OL҈l7 )9 ذ A:`!fjUÅIȉ"+֝3\\7ǽfİn?Hӵh?ʂLvRV\t<KN.f@jVӵYvpAWU)!-r@&1Jî\:YAn%5ht}%;Ԍ$ M ։%@Oj#EU[d\6݉XI]?FkAl2ZhWnft֤!^ ZFd29y56$1X|&l 0 ͧX /qT`ʚ;n0jmaԱϿ:};hʯ 'p&q-V.y"``szfm6wcorebird-1.1/examples/media2.jpg000066400000000000000000004032601260276623600166440ustar00rootroot00000000000000 XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmC     C     q  !1AQ "aq#2BR38bruv$67t59CScs%&4deFT'(GVWXEHUfw9!1A"Q2aRq#3B4$5%b ?ƄaXSn#=q^s}hhFk)dcwYQVTSVD"li.G@M_ŕ$8[5櫳] }zLkYy)IJ-౫Q}6^+X8 NzS娈P9$)r.>u )hQd{PQ">þA#dLpjhb-O@phUr=OqjvyF?T^Fnbѕ(R9.Arc[9;S9@ ,4vʂŻsI|@M$? @>ɩZ}zcΕlH c|S#Ra[TN?G?D|m咤}R$ ;ϺZ%Lɡ& EDV)B3|o#p&i/'exQ'o(rH='",,%)&3?S4d:Vvbedd /A ħhe#f>q-{ G)ܠ5a_F+KP'<Ϋy2is4AU!ʐA 7?_& Pr_^8'+.M{wJ8 Zf+(Ott4br7[ G r}m'=YGҲӒ{de+*E.bD wIs m6wj%\-p2PW. vuQYkMpx{S+{W(H)bt0QO"W67jE[4}Ҝ!Td-9Y4Qsf[s9z2Ð2 H=vXң~{ cNm °;b!㠦-QCG<뵠\;<Sܽ-=pu%6G6.Q|l܏BpֹzI㳻w2Ҵj/@ (rt$I ;oD7qRJDFbS ZMU/j3l();FR@:\<%9li$B/QpJ/6hӖf!ᾅC5,Y $t ZF]KAq722ȰqU,- X,_C ;MͅxЕOCKMșJj,֠ixk'S5Ig.67ڥ +P 6"{E4@}C [_R\(EЌi r)1kEq^KrwcK^Xn;lҥ%G(QmA`ԝe8;SBF/Fʵ2}Ex횉(jc.9{xh5ndW{H N1a{V$LjQWlN|kF6NN9E啥@ Rrv^Ie_It˃nCJ֗mMt4C7XBn[)Wb%l3bGtjhsè( b+IrĂ|JT6.ZK̠%0(K)A%f7>t4S8  zKreky[qJ9ʶ!"ShPWڪ譩:x6MSę 0ߺ txKFcE 8l& =(@%E{vlR?kR)"|6dq<=ʓ$E!7}G )n\Q-ƂXbÆi!&BM KjZs^җ{ZlrS줸J/B.R-Ӫ-o NT~uJ%! N1Sh >M48M1H@iH `Tpiu#Q[#+cVp&tu4N2@2_`V3B '.yNflcsEЇ7AP;Yb~-OܴJ qO(8Z? Nܪ8|_bѼfM-*KbI˓N(XX`Ƀh?_?'؁U[nwu(,|ƚ1F䊎iWCOtJsM X|4㰟o$=}fZ,&2Қy|gF|5y09 tY6j^ Z:IPl0< ͟st_m1!8MjZ)G>a'n❝[mH@%i 'ȿMĭ .]_\[DRBzY<1,*<=g]?i7q.O%*Q?cd.5v$ >5R?PK~9SοapVS%ɅrP>-Iϼ\W#Uϧ싃SK)s9Zܷ_OFd*;Ԉ銃U8jnvu1( 0mTJȟ42[VԗKOB0?ճv:Jl8\=䄭|=1E3ds}r.g;)lv͙B%oLYXQS,\[5tgdsm,dm+,)C\朏A<11?' %iLdr-~|G]NBI@RjZ:ZH!XoeJ>CjJFme[N쏄}򮾎tO,Ce}RB wcۊr\y5锠՞Y[#qC!UzxTr~'/NO^,M8EPš-<q"-!ζRPR<WC?o["ڔHSIx-lDy3#~{#b%!y4ɡ1'Ċ"=M`v>bCj i5[2Zu&< dU8KOߢ } _ҷ]݁))V6-1W PRJ 6\aR_TՐy: Qdbc*f{ ȉ(0)Jkv{/tlTsN lrh[VZVk"S-;a]OLai*ouҺsڔөQFr}vA^ %^H;e+Abܣ-*e'=ȢY6-)')VN7 JA=G(!=*|QV*p`}cQR@9vH@j=]a) \uJEIB,d=v<\6]!@}e#qYֵ/j㭚kҏNaKFZD%GQ84ChcWJTS0$LLzjӗ L9B)!J >F\B]g7+L w*N{TN"-/;|qW@2 -Ԅ'b3D@IE:L @4@o^.]5IAњb),x~(w"eEv /CHz:IҴyF0wq)|oB5bͯ.]}ʓ)Jx!="0GzLoM_s`C,Mz ,? fJW>: oD$+U"oawKEِ&s Umkv9Sns Հjs*?dJT#vO)T%,%V*u!S<~R>BksƤ%*UɒSoi~L$f]_YH]KΩ>(!ҴzX"k3aG߽!CpXHۙy RVßf'Ð5(]8{b" !sR:|M.DPKCrJB.TZP/٦a Wj}"ҝ$—5L,\wOiK [gt`LyܨLVPe+R;W{I+GNw}0R3- e[NA?߂:Sxc~iv.\)نUh6M 踰jK_.q U c-=wf MxrxW.|v󎼣ʭuEIg+\Sh PU`zDn245 KYH(aC (iJIdYѧWdzDU^6H:%-U;($2EL@bI*B%'6'mϦѰ8gj;x=$ U|b=Vh$|ەs$4jӏȞ٦?+K}<pŹZ\jUs)}!hP!C7ڳiqJQf~upȽ0hOBVӒP^.~}tԗj),][$ - ;g;T-` GMBT!FpӶIحnlі !u!er6KWkڌ+cM r= r>͏ fԈNHWpHΫiFiomXOAz\XFu ?M%FٷQoҮK ɞ@ݧJse5 [."BNMv4pn/?,k$/>bi&- ۏDYYR~sF[2CXZ5[\Uu6y7 >c m~gZdr3;5đV_jPi+|3D'X{j=.KDSR tGYqب($2Apb|V:vhܨ.(SA2QȖ]$Z.,܄DwZ1KHKeno?if,Q6ܴC$-Шg>JSpbz.O;;QGIF2V/6VTⵀ2NSR쭿MW٦xrqH7I>Gw.Ql) Zr)yY{P?Cw2yũILo7ԏ0O2BZ%~ȾXqxHn+21vW k ;=eb84OCI)ŋpM,j=l=gW+) RGsdGcS-an Q)rC l{+g'~=)`}NNt|vP'ʥ%XVWG"ci2km a]FRR]SB}ɬؚ2Y XWZtZhD%. 72S-ԍ$IkXEP};~.R4\h& Ɂẏ cCa#x Pm~*@a"irBI;gm[&:ڛxrgT{$,n7+CC(8#iF:Ne#Xqa<)4 Ioy?q>!T)=K 8|vADt8y~~ڜ&:kM%}(WF9U[BOEF,GxސwfSi igm9$,0؜b, B| 7cGI1UoF~8Js(64^ VS3+C. JzD!T񫔑qD! oRҾؓBCpFjTJK>)wd}ZImi>]m1{ΕvBqӣ:\) =wG)xl´֧}RpjK$q4j= NØVaJrAkeq-O|Ni'K y#[ |YKܧ-SɼnAeA ed6Rש4|=oCeA|m҅ )r~Lr"9&$-X }] %)5{byO; ̻ʝsO+Wd)tXJAD/I±0n_6a+ cH[>msߝ(L8>+yIî4]ϚWU~r6 [$3\,JzdKem,Nv)Mpy-,6){i盻4U(![z^K1mzn>G:) c5ӆM$xf]Q W7{vE5}@`^RƑ槹MdJGcNxpfɱ-;F2$ZDё_gT(8\.8eP~VrЁ[J_ wD'z64&M9V+ CMaHEPlU c62[zRhߤu[9UFE⩆-~)8/=0ESBSĝa Xo nRZQ*;9Dlރ1)m35.ѮN>y['4ˎ${@KbOa| 5GV([«ݾۖmOD4?1d_ha*<^=I/t&w2V͝)]ݵR4y;F Z@PBI$\ZIu'#p Pxѱ$HWp)mQ&w fG(ߠOZв_beW+$1ry )Š**j eIPW,օe\Q-9(8P>pҡEDGWQQ+90%-M[HOц,$+C9;C,\%m 1Jw}-WݬB)8dx7,OM]$QFqh%L&丕X4'1I*'Ψ[yWÈm]ZHSj v:TӇ!I:6| p7P@90>'2%GQT~Th޹:~vL 07ݐ/nq!s%{󫌫ɍ94%*5nQ%I#Xsu= MG( RN9n.y.Nt}/qEI$U+clٳEDANJF Q tmmjqKi&m|{yERHޮ;O/<GU&tIq*+J;-QT@lnZ|"JioiFۦ)CEwE&}ԅyQo)ᾄ+XKEFib0vZh]M j8hm)Ri{U)%MaA+ ő5v%G#O+<E.CK)3aLJTw)q$6Nf`1Z$xT4F}fRLʐ JTA:&i\Fd+_B#/V egK)M!>Ff x܃wbJ{k-1J('ѥ\ 82EY^&^qW `F{װ}RoWqer$k-iyb&:yOV۰=[\Z񹪎5$L:]Lr"AuӚ&뢢)m4-g5qo:uZ9{fIpk: 'Ua0`C3dz2ØY_L]0٪o?tZT2@<͂>tHӎ!G`+#EnN 8ՠft pm2jИ=oX[!*F?l IyS=3zy⒵_Gtn2p.-$xQtOxi8[xf\Ts+O1svR!~č9U_$-g``!pP9z?qa)S_[)BBzT!㗬(!?/oW#o9OGq_btlū+P8V}bnZ@8>t ]"lH8 ɥ5[%&lvkrzdc~8ސ,\W bơ+kTG}-PO@~@F.9ͽ:sAJ\[@U5͒yR; $t\L˃n}eobv,Ki3&ygVjr?\ ?x4aུm4(*>;\i=Ɲ%YsNC5ʽHێD&03(X%`> oFx3aGϡ{Z9>l2/x$Mvq7R5YnEߠ)=fi7&7= VhF+Nt2Օ2.. B2 ώ2@ V^BP'gzҤxW+dHI IBz{;&eҗ^Yp4A-}CVer4,QLFc6(t2*X!YqlJqOW#}w"oOmH,V ɐÄSmǢ(xf@v9H#_axEjShv298^|3%چo 7F]l%hnCl՝,CuZA[+?KqhJ?FCJiy"6+SqiRĻ΃v#B@y.:ϊRw hmKҽ!Cj$Qcޜ KP2c]-D%M8v%ƺ)n]ߵŔIYdץmȊ%0&WZ64M>2LE/։VjVQhB%)ڟe2^l )!*=Aӵv4Ql@q :-t. .\a6$"bvMq<èihRr{JȺ : <["yⲤlBVZ)b4gA9\\ c5V\Xu)QψV]f0`<\4<70\bhi!,,ɩڐrl/[ǗUcbnIn@.'rAޅנ{7{rIa=(ж#kjD{sB1y+9}tt%Y=z29 mBCR:o1è\Lr[A1F3NRj+)G% q4+gL)NN)P?h޻fSCxW__Gȥ3Dφ@Ȫޓfî&NVBJ G2F[B_1NT3bvǘIE>"6#|drʜՠW*VtLq"< oC&~hQ#ܻ9Qb`#ОN" ]q/Ç6 k{̭SnS+i%Ɩ%C ڜe2@¡}cGCB+AWwQuqp8ow& KL0^+ysN|fo#)<;@&cT\֔0J+m5cꃒjn6oֳ,^oLMpϯcܚBI 8&N/)J؊/|_ xHu R4zdVȷf“ʱֆߠddS`l{U4si #'jrHUuQr*4Ց2?)nlu Wjc%)DK{kk.˖*dO xq`d9 g+K%6"n-oK;tN|r> /XJO뭴7?a>\}a*8  3R6j-=-DIJV1jK#&K2B`Fs52Nb "UDPs99*t e]YR- Y*:dF$$0O("rKn|VN*5$ȤC4'~?Sl oSwU.˦G;4T/.Q!QyRm<ں($D\a(2POQڊH Aqn7,Ki?m>6L3JB9bUpjgMjD )w̐RSrV.=z$!JV 1RJ J"vK^Ͷ%JI+ku%*꒏y+{WKw8t!GEgCM8>0bcKe.@ar~6i$>:cd2D|v4=N,<,/i cqQ+ch)n]o*j%ɓM+kEaPP6>гEdzyǣT[ҏ$:e6"y`wi.]`8[9] 7٣x`ef[;qKyR05I%[^Ǒ_.;VF |'2:‚w)T54sީL[ FrtސxŷM ZDz1ԝϪx6+ \3HLG%q@ǸXAvV@BŹT ~>=lq'}B~Li+Q /8NJ楚˕qέDz] 1ZG17!B78MHPj<9=mu{:T!^__Xj ky_бPyxZ[R _ޮgw] IqMGZ[| mSG[]*Q+42ӓs!/$eQyGEam2B095QPG 6*ؑ+4688럑IQyV6s#֨-e,0\o/G_h˹6~fFjV<R:?!X}}:Y0W=(i'W+QH^ddhK^_1RV3*#+o w}LrI -TWtRRtHOiu#ScUaf '#jbrq5x^ zrSrJ3?IoW DNkFR#:ːs֯!}'r62ey؛kRwB/Y^*5džvdLt;:Jw#Y4G}n|SZQAĘJN=tD]LUx_ư:V j4ó[rR6 =G_32KmsҕC6!X ] ~0vݬO+5rru1ꬍ$oN̥r8ʇTiI GC#wIrI,oN9'/,(t@FO׃q;,5 M_T\Z"($k]\Pʶ'IM/˴kaiv3Kܥ])-X*V2P<AJȌj{6i*mIVjmh%5 T :0=vjo SU1.Gq< uCK-;xe.XUj膇N!կ [.3R[.͏k8{PCvŶ8W`QQ]-ΐ=RzQ&UpPuTTZJZoh'g[꣐Ni21Ź Ŏ{Rڇp6,EK vkEŔK-ئZ%MՄB赹tK5r>_h6FA?Yh h<13,M=i%YK8th{tc\mKCEJ$?z=pѐkqqAmu7:aIo͜G\4&X"Epk|Is)'dFաKwfWe%)G2-BLqCͩ*XkF\I#ENs؊TѾL8*Ĕ:ys֗IYlu*R)s|MjƾZoaI?J[Zv^cEq~y.8Qq.si*|^ IiO_Ab|K,14P@>Gɫ0XuO6Fɍ [>O~^’ yÅe7~.n 2f$R`E[RB9c?4[Оv!2Ԟ@(Rr+l_! >3a8ix&6|.T6]@wK^c`]}ƺ_yėxV8ewSx8ߴPxx dxH 4\i%ݮ"%`>5?ki>UmmGC QV]B@`+$ ޝ=n: K`={ř)l#._mbҩoJ=@J*栥[2-$%v(1V~Bcm ~48lG2_<| (NCp4YqtZ(&>hFmVO2\z *6kӷM4RJQ?e@rCQ[y;v5Kv 3 |P19c/Ҟ-Ɉ(Zwڷi3Y tacϒ<>e-#xPG)#eCMv'[ rqW5+>4y"mHyHyg Jz BKxy-wfJy|k-]śWib-+Um{)kkI[4v( =k>w߳ByHPޞ_`k4%OVcnp T֕0xk#]ůKߌu[ Ku9>F^5Jzʇ2櫐#Rze﫰J4:wC 1AB4k5vWz¥%y(OZf˱^9.L$lApWN` MD {\3LkI_^j%ş$-#oS߲8'Z= RL*2]J=^&DإN 9I 8W(PEK'qhs6+z b /¯-f K@] ߗC%R9Sh Kpi{ły ;%]i}OYpiE;ldR7#L*="PnT[l^\cNFB6n@zn搳tࢿE23h$"q)[s֥-[[]5بRFOJIrayK%Uz%p-L$lT4Z/c%zaI)O f{ zyƕO\\ g`u),Sn_Z\D3FYYzr9Irnv$khm/PR醭n2"J=@A&dGLKBV̄H usǘdz 'TK]P3lB*J^m vnSL[%JIQ?}7sE! PHX6kO7tYo䧨˜W[8ř[5ې=UWsȪAک.h':0\A/% ?4RȟajJ;@1;2s2~)SdJ(Q)#UAp%&e|55E*@ a-\S mVm@c48-d$x'nr#!؉`Ok]2x]5fT+D?TEX/VVQt%`pibl=AWZ .sa Mɇre%9(šR([•'xcc |eۂV%ҭ‘^K,d+S]ۥC;]!>$ƖtRwr¯/tynHɢh=~7+]a${[+jv%䲁G/Č#N jFP7B%(QǙNFx:i5 نY)!3IV;3M+w$#,cHHh5k٣ *KELrlYԑ'a>B!`+${},U k4tR ))q]بBW-%ᾚіzbLj[HO219'BW~pPkk\U_j@HC޳뫕V.:ܖN#? i^Ex^ ,+74>H=b'ٮQ2+c#>DnA4 / ivgn>K(ZB_M, =R OI (9S> 5kJ ?G5yӴwteX").8 9*=+"ڎ6R2>ɱ2pT z6)Xt+MV`+{tYfzCJ0[Q\[ 8qyvoH›m%Yi?}J,J P))s{b?wqk袥 #u|'bCD[[o -z8iC7t4qX$m=tοLj5ItaE0xD+ hȪ4` .O9u C_!a XcՆ@vnIQ}g~E=d6F<8ں H߉)cE Gw W'o #:J맦%$u$"xٳOy)͵Ԭ+;ԧ |@Pʈ5%du"A(NvK3li bSEj-8*cbonlkF 7m-/;P+9-I.XihW8[#.P j[ P=jP+n @swZBIEKe2>N6;GFIMI B -&d~T*=O]Z653\euNLm:sLp$g5ٺt-PZ@*(Dyc^r+Y9ړ,- Y}aeP ⳸m340;3ȝI6df[qȬ)Z#cƚFϦQ==֜䘥p~ Pˮ!t.gን$S}fi;u9RlXXYRsImqdHmլ>M.X/Ԇ6GIxa9ov(PAM8_`qhb7('8U\O.BYeX"λcPi$-Ӿ@Kԣѡ0ΎR`QO_8ibBq޵2Fi[4Y-H{%‘ڎҏL+d)(49dK8}cqUA_4=E)VK]`̤»4~*NǴiY#%&2Ty!8РR}d@bɑq-QJ/K[lԕgt%#&4[ ܇չ>>(`8nY 𩼯\Q1#!+Rqm4by-IJMEY?">d#4<&u Vc.RV/D|2(,q]T6h܇<1fpOy`y"YU4$ӯM;I]rD7/q^ث }0ҏhkz]O5M+%'<-t5j"n0Gin2^S c]ӎc)I қ1.ql1AIاqp"X|c 0h?b}/F,;)9XE#[l==0Dƌ߅ (4d\꒡9DLjtr=t(P_%0TjJ|oWd2_c$mChB%ZC$m}cJ69( R[Wħح^_f¤CdDǍZui$2cژ?*T$ڊdR7JØDo~ʯZ ܐtEsyr.En1PqD O&:4fve|gjq8 ^ꪊ a9*2lR~' K{ac-c8AJ>IpLI~91㭇l*-&[K.YS uA$'+iK%,6J_#sHXRlr b+jJCiI&P8=@9ٸ= =%jk&nwL*Tl%e2T@DDm)-0uʥ{g>7L_cqq7M:pן S.|;Pc+FV:n?OO&z%b$EHbu$d}T \@/Is`]hdghiN<}:Mz}y^d*3.:S%*eXH*IkP A$6<+P6RM ,Fg)^v"fn_<1F-FQm:Ŷ[(6)X8S2nַTt'=X)zv py Ԩ% 2R.S^!~7la;ڭ$G&/Jq~=! CەGX'vqN՝2D%R^DB3P }NYoV ¶Y0JH*L&:Bs֑dN%hYP[-@?]t&1o3L۩W BjѴ@(B84™qe8"Cո$gk7N:>JXՓő.EKM4W$HʘubDd}qҴ'hN.l2HK=~57I@=-`H&RT<'rhvMIJ~9Ӛ-Gmu.- }+jSXd9g3+~C{G.3zcU=yZ\U7`75?hzj|7It*T,#ViL丂8| 64'$GAiFoXaNqLɎtY u-M[y-z]Dʗ?BBZ[_@ڍJ%>on\/BPt4-Rh<6v?C)K1/%G`֟uᄪ+" -NrhGOeL!ƿ>Feȶѱ Ydc񣰓Fbi8¾((jcUέ|1O[\-9aE'O/8/0[-oDd>P[4Gna2vٶ6MJy׳iiRBBc4&8O..)Zr$)4M ;p_W=?hE4?EG9K'"C''lj< YVU9*8r aOR&$cVeVZme'sj2cL݋CMO?E[?GFuKAY?tYkd6G 95:ĝ/CED}R:^5h`+@.J^J :+j'>QGB_4;a.zd#=ƐճԵ(_L>^!d'$kɷ6- ,BCC1Zͮ~<--ma~i_YuM
    "); errors.foreach_element ((arr, index, node) => { var obj = node.get_object (); sb.append ("
  • ").append (obj.get_int_member ("code").to_string ()) .append (": ") .append (obj.get_string_member ("message")).append ("
  • "); }); sb.append ("
"); } error_message = sb.str; critical (json_data); show_error_dialog (error_message); } /** * download_file_async: * Downloads the given file asynchronously to the given location. * * @param url The URL of the file to download * @param path The filesystem path to save the file to * */ async void download_file_async(string url, string path, GLib.Cancellable? cancellable = null) { var msg = new Soup.Message("GET", url); GLib.SourceFunc cb = download_file_async.callback; SOUP_SESSION.queue_message(msg, (_s, _msg) => { if (cancellable.is_cancelled ()) { return; } try { File out_file = File.new_for_path(path); var out_stream = out_file.replace (null, false, FileCreateFlags.REPLACE_DESTINATION, null); out_stream.write_all (_msg.response_body.data, null); out_stream.close (); cb(); } catch (GLib.Error e) { critical (e.message); } }); yield; } public async void write_pixbuf_async (Gdk.Pixbuf pixbuf, GLib.OutputStream out_stream, string type) { new Thread ("write_pixbuf", () => { try { pixbuf.save_to_stream (out_stream, type); } catch (GLib.Error e) { warning (e.message); return null; } GLib.Idle.add (() => { write_pixbuf_async.callback (); return false; }); return null; }); yield; } string unescape_html (string input) { string back = input.replace ("<", "<"); back = back.replace (">", ">"); back = back.replace ("&", "&"); return back; } public void load_custom_icons () { var icon_theme = Gtk.IconTheme.get_default (); icon_theme.add_resource_path ("/org/baedert/corebird/data/"); } public void load_custom_css () { try { var provider = new Gtk.CssProvider (); provider.load_from_file(File.new_for_uri ("resource:///org/baedert/corebird/ui/style.css")); Gtk.StyleContext.add_provider_for_screen ((!)Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); }catch (GLib.Error e) { warning ("Error while loading ui/style.css: %s", e.message); } } public void init_soup_session () { assert (SOUP_SESSION == null); SOUP_SESSION = new Soup.Session (); } string capitalize (string s) { string back = s; if (s.get_char (0).islower ()) { back = s.get_char (0).toupper ().to_string () + s.substring (1); } return back; } uint int64_hash_func (int64? k) { return (uint)k; } bool int64_equal_func (int64? a, int64? b) { return a == b; } /** * Calculates the region of the image the thumbnail should be composed of. * * @param img_width The width of the original image * @param img_height The height of the original image * */ private void calc_thumb_square (int img_width, int img_height, out int x, out int y, out int width, out int height) { float ratio = img_width / (float)img_height; if (ratio >= 0.9 && ratio <= 1.1) { // it's more or less squared, so... x = y = 0; width = img_width; height = img_height; } else if (ratio > 1.1) { // The image is pretty wide but not really high x = (img_width/2) - (img_height/2); y = 0; width = height = img_height; } else { x = 0; y = (img_height/2) - (img_width/2); width = height = img_width; } } private void calc_thumb_rect (int img_width, int img_height, int thumb_width, int thumb_height, out int x, out int y, out int w, out int h) { float f = (float)img_width / (float)thumb_width; w = img_width; h = (int)(thumb_height * f); if (h > img_height) h = img_height; x = 0; y = (img_height / 2) - (h / 2); } /** * Slices the given pixbuf to a smaller thumbnail image. * * @param pic The Gdk.Pixbuf to use as base image * * @return The created thumbnail */ public Gdk.Pixbuf slice_pixbuf (Gdk.Pixbuf pic, int thumb_width, int thumb_height = -1) { int x = 0, y = 0, w = 0, h = 0; if (thumb_height == -1) thumb_height = thumb_width; if (thumb_width == thumb_height) { Utils.calc_thumb_square (pic.get_width (), pic.get_height (), out x, out y, out w, out h); } else { Utils.calc_thumb_rect (pic.get_width (), pic.get_height (), thumb_width, thumb_height, out x, out y, out w, out h); } var big_thumb = new Gdk.Pixbuf (Gdk.Colorspace.RGB, true, 8, w, h); pic.copy_area (x, y, w, h, big_thumb, 0, 0); var thumb = big_thumb.scale_simple (thumb_width, thumb_height, Gdk.InterpType.TILES); return thumb; } public int get_json_array_size (Json.Object node, string object_name) { if (!node.has_member (object_name)) return 0; return (int)node.get_array_member (object_name).get_length (); } /** * Checks if @value is existing in @node and if it is, non-null. * * Returns TRUE if the @value does both exist and is non-null. */ public bool usable_json_value (Json.Object node, string value_name) { if (node.get_null_member (value_name)) return false; return node.has_member (value_name); } public string get_banner_name (int64 user_id) { return user_id.to_string () + ".png"; } public void update_startup_account (string old_screen_name, string new_screen_name) { string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); string[] new_startup_accounts = new string[startup_accounts.length]; for (int i = 0; i < startup_accounts.length; i ++) { if (startup_accounts[i] != old_screen_name) new_startup_accounts[i] = startup_accounts[i]; else new_startup_accounts[i] = new_screen_name; } Settings.get ().set_strv ("startup-accounts", new_startup_accounts); } public Filter create_persistent_filter (string content, Account account) { int id = (int)account.db.insert ("filters") .val ("content", content) .run(); Filter f = new Filter (content); f.id = id; account.add_filter (f); return f; } } corebird-1.1/src/util/WeakRef.vala000066400000000000000000000016651260276623600171230ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class WeakRef : GLib.Object { private GLib.WeakRef wr; public WeakRef (G obj) { this.wr = GLib.WeakRef ((GLib.Object)obj); } public new G get () { return wr.get (); } } corebird-1.1/src/widgets/000077500000000000000000000000001260276623600154135ustar00rootroot00000000000000corebird-1.1/src/widgets/AccountCreateWidget.vala000066400000000000000000000124711260276623600221510ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/account-create-widget.ui")] class AccountCreateWidget : Gtk.Box { [GtkChild] private Gtk.Entry pin_entry; [GtkChild] private Gtk.Label error_label; [GtkChild] private Gtk.Button confirm_button; [GtkChild] private Gtk.Button request_pin_button; [GtkChild] private Gtk.Label info_label; private unowned Account acc; private unowned Corebird corebird; public signal void result_received (bool result, Account acc); public AccountCreateWidget (Account acc, Corebird corebird) { this.acc = acc; this.corebird = corebird; info_label.label = "%s %s" .printf (_("Don't have an account yet?"), _("Create one")); pin_entry.buffer.deleted_text.connect (pin_changed_cb); pin_entry.buffer.inserted_text.connect (pin_changed_cb); } public void open_pin_request_site () { acc.init_proxy (false, true); string? uri = null; try { acc.proxy.request_token ("oauth/request_token", "oob"); uri = "http://twitter.com/oauth/authorize?oauth_token=" + acc.proxy.get_token(); debug ("Trying to open %s", uri); } catch (GLib.Error e) { if (e.message.down() == "unauthorized") { Utils.show_error_dialog (_("Unauthorized. Most of the time, this means that there's something wrong with the Twitter servers and you should try again later")); } else { Utils.show_error_dialog (e.message); } critical (e.message); return; } /* Try to open URI in browser */ try { if (!GLib.AppInfo.launch_default_for_uri (uri, null)) { error_label.label = _("Could not open %s").printf ("" + uri + ""); error_label.show (); } } catch (GLib.Error e) { Utils.show_error_dialog (e.message); critical (e.message); } } [GtkCallback] private void request_pin_clicked_cb () { open_pin_request_site (); } [GtkCallback] private void confirm_button_clicked_cb () { pin_entry.sensitive = false; confirm_button.sensitive = false; request_pin_button.sensitive = false; try { acc.proxy.access_token("oauth/access_token", pin_entry.get_text()); } catch (GLib.Error e) { critical (e.message); // We just assume that it was the wrong code show_error (_("Wrong PIN")); pin_entry.sensitive = true; confirm_button.sensitive = true; request_pin_button.sensitive = true; return; } // The token and token secret have been successfully received // So, get some account information var call = acc.proxy.new_call (); call.set_function ("1.1/account/settings.json"); call.set_method ("GET"); call.invoke_async.begin (null, (obj, res) => { var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical ("Problem with JSON Data: %s\n%s", e.message, call.get_payload ()); } var root = parser.get_root ().get_object (); string screen_name = root.get_string_member ("screen_name"); debug ("Checking for %s", screen_name); unowned GLib.SList current_accounts = Account.list_accounts (); foreach (var a in current_accounts) { if (a.screen_name == screen_name) { result_received (false, a); critical ("Account is already in use"); show_error (_("Account already in use")); pin_entry.sensitive = true; pin_entry.text = ""; request_pin_button.sensitive = true; return; } } acc.query_user_info_by_screen_name.begin (screen_name, (obj, res) => { acc.query_user_info_by_screen_name.end (res); debug ("user info call"); acc.init_database (); acc.save_info(); acc.db.insert ("common") .val ("token", acc.proxy.token) .val ("token_secret", acc.proxy.token_secret) .run (); acc.init_proxy (true, true); // TODO: Insert account into app menu corebird.account_added (acc); result_received (true, acc); }); }); } private void show_error (string err) { info_label.visible = false; error_label.visible = true; error_label.label = err; } private void pin_changed_cb () { string text = pin_entry.get_text (); bool confirm_possible = text.length > 0 && acc.proxy != null; confirm_button.sensitive = confirm_possible; } [GtkCallback] private bool delete_event_cb () { Account.remove_account (Account.DUMMY); return false; } } corebird-1.1/src/widgets/AddImageButton.vala000066400000000000000000000152451260276623600211160ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ /** * Trimmed-down version of MediaButton, used in the Compose Widow * to add new images. */ public class AddImageButton : Gtk.Button { private static const uint TARGET_STRING = 1; private static const uint TARGET_URI_LIST = 2; private static const uint TARGET_IMAGE = 3; private static const int ICON_SIZE = 32; private new Gdk.Pixbuf? _image; public new Gdk.Pixbuf? image { set { this._image = value; if (value != null) { this.get_style_context ().remove_class ("image-placeholder"); this.get_style_context ().add_class ("image-added"); this.tooltip_text = _("Click to remove image"); } else { this.get_style_context ().add_class ("image-placeholder"); this.get_style_context ().remove_class ("image-added"); this.get_style_context ().remove_class ("image-error"); this.get_style_context ().remove_class ("image-progress"); this.tooltip_text = _("Click to add image"); } this.queue_draw (); } get { return _image; } } public string? image_path = null; private string? error_message = null; public signal void add_clicked (); public signal void remove_clicked (); public AddImageButton () { this.clicked.connect (() => { if (_image == null && error_message == null) { add_clicked (); } else { error_message = null; remove_clicked (); } }); /* DND stuff */ const Gtk.TargetEntry[] target_entries = { {"STRING", 0, TARGET_STRING}, {"text/plain", 0, TARGET_STRING}, {"text/uri-list", 0, TARGET_URI_LIST}, {"image/png", 0, TARGET_IMAGE}, {"image/jpeg", 0, TARGET_IMAGE}, }; Gtk.drag_dest_set (this, Gtk.DestDefaults.ALL, target_entries, Gdk.DragAction.COPY); this.drag_data_received.connect (drag_data_received_cb); } construct { this.image = null; this.set_size_request (-1, MultiMediaWidget.HEIGHT); } public override bool draw (Cairo.Context ct) { int widget_width = get_allocated_width (); int widget_height = get_allocated_height (); Gtk.StyleContext style_context = this.get_style_context (); /* Draw thumbnail */ if (this._image != null) { ct.save (); ct.rectangle (0, 0, widget_width, widget_height); double scale = (double)widget_width / _image.get_width (); ct.scale (scale, 1); Gdk.cairo_set_source_pixbuf (ct, _image, 0, 0); ct.fill (); ct.restore (); } base.draw (ct); if (error_message == null) { style_context.render_check (ct, (widget_width / 2.0) - (ICON_SIZE / 2.0), (widget_height / 2.0) - (ICON_SIZE / 2.0), ICON_SIZE, ICON_SIZE); } else { style_context.render_check (ct, 20, (widget_height / 2.0) - (ICON_SIZE / 2.0), ICON_SIZE, ICON_SIZE); Pango.Layout error_layout = this.create_pango_layout (this.error_message); error_layout.set_width ((widget_width - ICON_SIZE - 20 - 20 - 20) * Pango.SCALE); error_layout.set_height ((widget_height - 20) * Pango.SCALE); style_context.render_layout (ct, 20 + ICON_SIZE + 20, (widget_height / 2.0) - (error_layout.get_height () / Pango.SCALE / 2.0), error_layout); } return false; } private void drag_data_received_cb (Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time) { if (info == TARGET_STRING) { var uri = selection_data.get_text ().strip (); var file = GLib.File.new_for_uri (uri); from_file (file); } else if (info == TARGET_IMAGE) { /* XXX This doesn't work when uploading since it doesn't set image_path? */ var pixbuf = selection_data.get_pixbuf (); from_bigger_pixbuf (pixbuf); } else if (info == TARGET_URI_LIST) { var uris = selection_data.get_uris (); var file = GLib.File.new_for_uri (uris[0]); if (file.get_uri_scheme () == "file") { from_file (file); } } } private void from_file (GLib.File file) { try { var pixbuf = new Gdk.Pixbuf.from_file (file.get_path ()); this.image_path = file.get_path (); from_bigger_pixbuf (pixbuf); } catch (GLib.Error e) { warning (e.message); } } private void from_bigger_pixbuf (Gdk.Pixbuf pixbuf) { var thumb = Utils.slice_pixbuf (pixbuf, this.get_allocated_width (), MultiMediaWidget.HEIGHT); this.image = thumb; } public void set_error (string error_message) { this.get_style_context ().remove_class ("image-progress"); this.get_style_context ().remove_class ("image-success"); this.get_style_context ().add_class ("image-added"); if (this.image == null) { warning ("Progress started but image == null"); } this.get_style_context ().add_class ("image-error"); this.error_message = error_message; this.set_tooltip_text (_("Click to remove image")); } public void start_progress () { this.get_style_context ().remove_class ("image-added"); if (this.image == null) { warning ("Progress started but image == null"); } this.get_style_context ().add_class ("image-progress"); } public void set_success () { this.get_style_context ().remove_class ("image-progress"); this.get_style_context ().remove_class ("image-added"); if (this.image == null) { warning ("Progress started but image == null"); } this.get_style_context ().add_class ("image-success"); this.set_tooltip_text (""); } } corebird-1.1/src/widgets/AspectImage.vala000066400000000000000000000101711260276623600204420ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class AspectImage : Gtk.Widget { public Gdk.Pixbuf pixbuf { set { if (value != null) { if (value != Twitter.no_banner) { start_animation (); } if (this.pixbuf_surface != null) this.old_surface = this.pixbuf_surface; this.pixbuf_surface = (Cairo.ImageSurface)Gdk.cairo_surface_create_from_pixbuf (value, 1, this.get_window ()); } this.queue_draw (); } } private double _scale = 1.0; public double scale { get { return _scale; } set { if (value > 1.0) value = 1.0; this._scale = value; this.queue_resize (); } } private Cairo.Surface? old_surface; private Cairo.ImageSurface pixbuf_surface; public AspectImage () {} construct { set_has_window (false); } private void start_animation () { if (!this.get_realized ()) return; alpha = 0.0; in_transition = true; this.start_time = this.get_frame_clock ().get_frame_time (); this.add_tick_callback (fade_in_cb); } private double ease_out_cubic (double t) { double p = t - 1; return p * p * p +1; } private const double TRANSITION_DURATION = 200 * 1000; private double alpha = 0.0; private int64 start_time; private bool in_transition = false; private bool fade_in_cb (Gtk.Widget widget, Gdk.FrameClock frame_clock) { int64 now = frame_clock.get_frame_time (); double t = (now - start_time) / TRANSITION_DURATION; if (t >= 1.0) { t = 1.0; in_transition = false; } this.alpha = ease_out_cubic (t); this.queue_draw (); return t < 1.0; } public override void get_preferred_height_for_width (int width, out int min_height, out int nat_height) { if (pixbuf_surface == null) { min_height = 0; nat_height = 1; return; } double scale_x = width / (double)pixbuf_surface.get_width (); if (scale_x > 1) scale_x = 1; double final_height = scale_x * pixbuf_surface.get_height (); min_height = (int)(final_height * _scale); nat_height = (int)(final_height * _scale); } public override Gtk.SizeRequestMode get_request_mode () { return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; } public override bool draw (Cairo.Context ct) { if (this.pixbuf_surface == null) return false; int width = get_allocated_width (); int height = get_allocated_height (); double scale_x = width / (double)pixbuf_surface.get_width (); double scale_y = scale_x; int y = 0; /* Never scale it vertically down, instead move it up */ if (scale_y > 1) { scale_y = 1; } int view_height = (int)(pixbuf_surface.get_height () * scale_y); y = height - view_height; ct.rectangle (0, 0, width, view_height); ct.scale (scale_x, scale_y); ct.push_group (); if (this.old_surface != null) { ct.set_source_surface (this.old_surface, 0, 0); ct.paint (); } else alpha = 1.0; ct.set_source_surface (this.pixbuf_surface, 0, 0); if (in_transition) ct.paint_with_alpha (alpha); else ct.paint (); ct.pop_group_to_source (); ct.set_operator (Cairo.Operator.OVER); ct.paint (); return Gdk.EVENT_PROPAGATE; } } corebird-1.1/src/widgets/AvatarBannerWidget.vala000066400000000000000000000135701260276623600217760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class AvatarBannerWidget : Gtk.Container { private static const double BANNER_RATIO = 0.5; /* 320/640 */ public int avatar_size { get; set; default = 48; } private unowned Account account; private PixbufButton set_banner_button; private PixbufButton set_avatar_button; public signal void avatar_changed (Gdk.Pixbuf new_avatar); public signal void banner_changed (Gdk.Pixbuf new_banner); construct { this.set_has_window (false); get_style_context ().add_class ("avatar"); /* set_banner_button */ this.set_banner_button = new PixbufButton (); set_banner_button.show_all (); set_banner_button.clicked.connect (banner_clicked_cb); this.add (set_banner_button); /* set_avatar_button */ this.set_avatar_button = new PixbufButton (); set_avatar_button.show_all (); set_avatar_button.clicked.connect (avatar_clicked_cb); this.add (set_avatar_button); Settings.get ().bind ("round-avatars", set_avatar_button, "round", GLib.SettingsBindFlags.DEFAULT); } public void set_account (Account account) { this.account = account; load_banner.begin (); this.queue_draw (); set_avatar_button.set_bg ((Cairo.ImageSurface)account.avatar); } private async void load_banner () { string banner_name = Utils.get_banner_name (account.id); string banner_path = Dirs.cache ("assets/banners/" + banner_name); /* Try to load the banner */ try { var stream = GLib.File.new_for_path (banner_path).read (); set_banner_button.set_pixbuf (yield new Gdk.Pixbuf.from_stream_async (stream, null)); stream.close(); } catch (GLib.Error e) { if (e is GLib.IOError.NOT_FOUND) { /* Banner does not exist locally so we need to fetch it */ yield fetch_banner (banner_path); } else { warning (e.message); } } } public override bool draw (Cairo.Context ct) { this.propagate_draw (set_banner_button, ct); this.propagate_draw (set_avatar_button, ct); return true; } private int get_avatar_x () { return (get_allocated_width () / 2) - (avatar_size / 2); } private int get_avatar_y () { return get_allocated_height () - avatar_size; } public override Gtk.SizeRequestMode get_request_mode () { return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; } public override void get_preferred_width (out int min, out int nat) { min = avatar_size + 40; // 20px margin on either side nat = min; } public override void get_preferred_height_for_width (int width, out int min, out int nat) { nat = (int)(width * BANNER_RATIO) + (avatar_size / 3); min = (int)(width * BANNER_RATIO) + (avatar_size / 3); } private async void fetch_banner (string banner_path) { if (account.banner_url == null) { set_banner_button.set_pixbuf (Twitter.no_banner); return; } yield Utils.download_file_async (account.banner_url, banner_path); try { this.set_banner_button.set_pixbuf (new Gdk.Pixbuf.from_file (banner_path)); } catch (GLib.Error e) { warning (e.message); } } public override void size_allocate (Gtk.Allocation allocation) { this.set_allocation (allocation); Gtk.Requisition child_requisition; Gtk.Allocation child_allocation = Gtk.Allocation(); /* set_banner_button */ set_banner_button.get_preferred_size (out child_requisition, null); child_allocation.x = allocation.x; child_allocation.y = allocation.y; child_allocation.width = allocation.width; child_allocation.height = (int)(allocation.width * BANNER_RATIO); set_banner_button.size_allocate (child_allocation); /* set_avatar_button */ child_allocation.x = get_avatar_x () + allocation.x; child_allocation.y = get_avatar_y () + allocation.y; child_allocation.width = avatar_size; child_allocation.height = avatar_size; set_avatar_button.size_allocate (child_allocation); } public override void add (Gtk.Widget w) { w.set_parent (this); } public override void remove (Gtk.Widget w) { w.unparent (); } public override void forall_internal (bool include_internals, Gtk.Callback cb) { cb (set_banner_button); cb (set_avatar_button); } private void banner_clicked_cb () { ImageCropDialog dialog = new ImageCropDialog (2.0); dialog.set_title (_("Select banner")); dialog.set_min_size (200); dialog.set_modal (true); dialog.min_width = 200; dialog.min_height = 100; dialog.set_transient_for ((Gtk.Window)this.get_toplevel ()); dialog.image_cropped.connect ((img) => { set_banner_button.set_pixbuf (img); banner_changed (img); }); dialog.show_all (); } private void avatar_clicked_cb () { ImageCropDialog dialog = new ImageCropDialog (1.0); dialog.set_title (_("Select avatar")); dialog.set_modal (true); dialog.set_transient_for ((Gtk.Window)this.get_toplevel ()); dialog.image_cropped.connect ((img) => { set_avatar_button.set_pixbuf (img); avatar_changed (img); }); dialog.show_all (); } } corebird-1.1/src/widgets/AvatarWidget.vala000066400000000000000000000112371260276623600206460ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class AvatarWidget : Gtk.Widget { private static const int SMALL = 0; private static const int LARGE = 1; private bool _round = true; public bool make_round { get { return _round; } set { if (value) { this.get_style_context ().add_class ("avatar-round"); } else { this.get_style_context ().remove_class ("avatar-round"); } this._round = value; this.queue_draw (); } } public bool verified { get; set; default = false; } private Cairo.Surface _surface; public Cairo.Surface surface { get { return _surface; } set { if (this._surface != null) Twitter.unref_avatar (this._surface); this._surface = value; if (this._surface != null) Twitter.ref_avatar (this._surface); this.queue_draw (); } } static Cairo.Surface[] verified_icons; static const int[] VERIFIED_SIZES = {12, 18}; static construct { try { verified_icons = { Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/verified-small.png"), 1, null), Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/verified-large.png"), 1, null), Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/verified-small@2.png"), 2, null), Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/verified-large@2.png"), 2, null) }; } catch (GLib.Error e) { critical (e.message); } } construct { this.set_has_window (false); Settings.get ().bind ("round-avatars", this, "make_round", GLib.SettingsBindFlags.DEFAULT); } ~AvatarWidget () { if (this._surface != null) Twitter.unref_avatar (this._surface); } public override bool draw (Cairo.Context ctx) { int width = this.get_allocated_width (); int height = this.get_allocated_height (); if (this._surface == null) { return false; } if (width != height) { warning ("Avatar with mapped with width %d and height %d", width, height); } var surface = new Cairo.Surface.similar (ctx.get_target (), Cairo.Content.COLOR_ALPHA, width, height); var ct = new Cairo.Context (surface); ct.rectangle (0, 0, width, height); ct.set_source_surface (this._surface, 0, 0); ct.fill(); var sc = this.get_style_context (); if (_round) { // make it round ct.set_operator (Cairo.Operator.DEST_IN); ct.arc ((width / 2.0), (height / 2.0), (width / 2.0) - 0.5, /* Radius */ 0, /* Angle from */ 2 * Math.PI); /* Angle to */ ct.fill (); // draw outline sc.render_frame (ctx, 0, 0, width, height); } ctx.rectangle (0, 0, width, height); ctx.set_source_surface (surface, 0, 0); ctx.fill (); /* Draw verification indicator */ if (verified) { int index = SMALL; if (width > 48) index = LARGE; int scale_factor = this.get_scale_factor () - 1; Cairo.Surface verified_img = verified_icons[scale_factor * 2 + index]; ctx.rectangle (0, 0, width, height); ctx.set_source_surface (verified_img, width - VERIFIED_SIZES[index], 0); ctx.fill (); } return GLib.Source.CONTINUE; } public override void get_preferred_height (out int minimal, out int natural) { if (this._surface == null) { minimal = 0; natural = 0; } else { minimal = ((Cairo.ImageSurface)this._surface).get_height (); natural = ((Cairo.ImageSurface)this._surface).get_height (); } } } corebird-1.1/src/widgets/BadgeRadioToolButton.vala000066400000000000000000000040011260276623600222660ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class BadgeRadioToolButton : Gtk.RadioButton { private static const int BADGE_SIZE = 10; private bool _show_badge = false; public bool show_badge { set { debug ("New show_badge value: %s", value ? "true" : "false"); this._show_badge = value; this.queue_draw (); } get { return this._show_badge; } } public BadgeRadioToolButton (Gtk.RadioButton group, string icon_name, string text="") { GLib.Object (group: group); this.get_style_context ().add_class ("image-button"); var i = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.BUTTON); this.add (i); this.set_mode (false); this.focus_on_click = false; if (text != "") { this.tooltip_text = text; Atk.Object accessible = this.get_accessible (); accessible.set_name (text); } } public override bool draw (Cairo.Context c) { base.draw (c); if (!show_badge) return false; var context = this.get_style_context (); int width = get_allocated_width (); context.save (); context.add_class ("badge"); context.render_background (c, width - BADGE_SIZE, 0, BADGE_SIZE, BADGE_SIZE); context.render_frame (c, width - BADGE_SIZE, 0, BADGE_SIZE, BADGE_SIZE); context.restore (); return false; } } corebird-1.1/src/widgets/CompletionTextView.vala000066400000000000000000000213651260276623600221000ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class CompletionTextView : Gtk.TextView { private Gtk.ListBox completion_list; private Gtk.Window completion_window; private int current_match = 0; private unowned Account account; construct { completion_window = new Gtk.Window (Gtk.WindowType.POPUP); completion_window.set_type_hint (Gdk.WindowTypeHint.COMBO); completion_window.focus_out_event.connect (completion_window_focus_out_cb); completion_window.set_screen (this.get_screen ()); completion_list = new Gtk.ListBox (); var scroller = new Gtk.ScrolledWindow (null, null); scroller.add (completion_list); completion_window.add (scroller); this.focus_out_event.connect (completion_window_focus_out_cb); /* Your theme uses a wildcard for :link, right? */ var style_context = this.get_style_context (); Gdk.RGBA link_color = style_context.get_color (Gtk.StateFlags.LINK); if (link_color.red == 1.0 && link_color.green == 1.0 && link_color.blue == 1.0 && link_color.alpha == 1.0) { /* Unset, fall back to Adwaita's default */ link_color = { 0.16470, 0.462735, 0.77647, 1.0 }; } this.buffer.create_tag ("link", "foreground_rgba", link_color, null); this.buffer.create_tag ("mention", "foreground_rgba", link_color, null); this.buffer.create_tag ("hashtag", "foreground_rgba", link_color, null); this.buffer.notify["cursor-position"].connect (update_completion); this.buffer.changed.connect (buffer_changed_cb); this.key_press_event.connect (key_press_event_cb); } public void set_account (Account account) { this.account = account; } private bool insert_snippet () { Gtk.TextIter cursor_word_start; Gtk.TextIter cursor_word_end; string cursor_word = get_cursor_word (out cursor_word_start, out cursor_word_end); /* See the git log for an explanation */ if (cursor_word.get_char (0) == ' ' || cursor_word.get_char (0) == '\t' || cursor_word.get_char (0) == '\n') { cursor_word = cursor_word.substring (1); cursor_word_start.forward_char (); } string? snippet = Corebird.snippet_manager.get_snippet (cursor_word.strip ()); if (snippet == null) { debug ("No snippet for cursor_word '%s' found.", cursor_word); return false; } Gtk.TextIter start_word_iter; this.buffer.freeze_notify (); this.buffer.delete_range (cursor_word_start, cursor_word_end); Gtk.TextMark cursor_mark = this.buffer.get_insert (); this.buffer.get_iter_at_mark (out start_word_iter, cursor_mark); this.buffer.insert_text (ref start_word_iter, snippet, snippet.length); this.buffer.thaw_notify (); return true; } private inline bool snippets_configured () { return Corebird.snippet_manager.n_snippets () > 0; } public bool key_press_event_cb (Gdk.EventKey evt) { if (evt.keyval == Gdk.Key.Tab && snippets_configured ()) { return insert_snippet (); } /* If we are not in 'completion mode' atm, just back out. */ if (!completion_window.visible) return false; int n_results = (int)completion_list.get_children ().length (); if (evt.keyval == Gdk.Key.Down) { if (n_results == 0) return false; this.current_match = (current_match + 1) % n_results; var row = completion_list.get_row_at_index (current_match); completion_list.select_row (row); return true; } else if (evt.keyval == Gdk.Key.Up) { current_match --; if (current_match < 0) current_match = n_results - 1; var row = completion_list.get_row_at_index (current_match); completion_list.select_row (row); return true; } else if (evt.keyval == Gdk.Key.Return) { if (n_results == 0) return false; if (current_match == -1) current_match = 0; var row = completion_list.get_row_at_index (current_match); string compl = ((Gtk.Label)(((Gtk.ListBoxRow)row).get_child ())).label; insert_completion (compl.substring (1)); current_match = -1; completion_window.hide (); return true; } else if (evt.keyval == Gdk.Key.Escape) { completion_window.hide (); return true; } return false; } private void buffer_changed_cb () { Gtk.TextIter? start_iter; Gtk.TextIter? end_iter; this.buffer.get_start_iter (out start_iter); this.buffer.get_end_iter (out end_iter); this.buffer.remove_all_tags (start_iter, end_iter); TweetUtils.annotate_text (this.buffer); } private void show_completion_window () { debug ("show_completion_window"); if (!this.get_mapped ()) return; int x, y; Gtk.Allocation alloc; this.get_allocation (out alloc); this.get_window (Gtk.TextWindowType.WIDGET).get_origin (out x, out y); y += alloc.height; completion_window.move (x, y); completion_window.resize (alloc.width, 50); completion_list.foreach ((w) => { completion_list.remove (w);}); completion_window.show_all (); } private bool completion_window_focus_out_cb () { completion_window.hide (); return false; } private void update_completion () { string cur_word = get_cursor_word (null, null); /* Check if the word ends with a 'special' character like ?!_ */ char end_char = cur_word.get (cur_word.char_count () - 1); bool word_has_alpha_end = (end_char.isalpha () || end_char.isdigit ()) && end_char.isgraph () || end_char == '@'; if (!cur_word.has_prefix ("@") || !word_has_alpha_end || this.buffer.has_selection) { completion_window.hide (); return; } show_completion_window (); // Strip off the @ cur_word = cur_word.substring (1); int corpus_size = 0; var corpus = account.user_counter.query_by_prefix (cur_word, 10, out corpus_size); for (int i = 0; i < corpus_size; i++) { var l = new Gtk.Label ("@" + corpus[i].screen_name); l.halign = Gtk.Align.START; completion_list.add (l); } if (corpus_size > 0) { completion_list.select_row (completion_list.get_row_at_index (0)); current_match = 0; } completion_list.show_all (); } private string get_cursor_word (out Gtk.TextIter start_iter, out Gtk.TextIter end_iter) { Gtk.TextMark cursor_mark = this.buffer.get_insert (); Gtk.TextIter cursor_iter; this.buffer.get_iter_at_mark (out cursor_iter, cursor_mark); /* Check if the current "word" is just "@" */ var test_iter = Gtk.TextIter (); test_iter.assign (cursor_iter); for (;;) { Gtk.TextIter left_iter = test_iter; left_iter.assign (test_iter); left_iter.backward_char (); string s = this.buffer.get_text (left_iter, test_iter, false); unichar c = s.get_char (0); assert (s.char_count () == 1 || s.char_count () == 0); if (left_iter.is_start ()) test_iter.assign (left_iter); if (c.isspace() || left_iter.is_start ()) { break; } test_iter.assign (left_iter); } start_iter = test_iter; start_iter.assign (test_iter); end_iter = cursor_iter; end_iter.assign (cursor_iter); return this.buffer.get_text (test_iter, cursor_iter, false); } private void insert_completion (string compl) { this.buffer.freeze_notify (); Gtk.TextIter start_word_iter; Gtk.TextIter end_word_iter; string word_to_delete = get_cursor_word (out start_word_iter, out end_word_iter); debug ("Delete word: %s", word_to_delete); this.buffer.delete_range (start_word_iter, end_word_iter); Gtk.TextMark cursor_mark = this.buffer.get_insert (); this.buffer.get_iter_at_mark (out start_word_iter, cursor_mark); this.buffer.insert_text (ref start_word_iter, "@" + compl + " ", compl.length + 2); this.buffer.thaw_notify (); } } corebird-1.1/src/widgets/CropWidget.vala000066400000000000000000000275341260276623600203420ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class CropWidget : Gtk.DrawingArea { private const int MIN_SIZE = 48; private Gdk.Pixbuf? image; private Gdk.Rectangle selection_rect; private Gdk.Rectangle image_rect; private Gdk.Cursor drag_cursor; private Gdk.Cursor default_cursor; private Gdk.Cursor resize_cursor; private bool selection_grabbed = false; private bool resize_area_grabbed = false; private int drag_diff_x = 0; private int drag_diff_y = 0; private int resize_diff_x = 0; private int resize_diff_y = 0; private bool resize_area_hovered = false; private double current_scale = 1.0; private int min_width = MIN_SIZE; /** * Ratio of the width to the height, i.e. (width/height) * => values >1.0 for landscape pictures */ public double desired_aspect_ratio { get; set; default = 0.8; } construct { this.set_events (this.get_events () | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK); this.motion_notify_event.connect (mouse_motion_cb); this.button_press_event.connect (button_press_cb); this.button_release_event.connect (button_release_cb); this.drag_cursor = new Gdk.Cursor.for_display (this.get_display (), Gdk.CursorType.FLEUR); this.default_cursor = new Gdk.Cursor.for_display (this.get_display (), Gdk.CursorType.ARROW); this.resize_cursor = new Gdk.Cursor.for_display (this.get_display (), Gdk.CursorType.BOTTOM_RIGHT_CORNER); this.image_rect = Gdk.Rectangle (); this.selection_rect = Gdk.Rectangle (); } private bool mouse_motion_cb (Gdk.EventMotion evt) { double x = evt.x; double y = evt.y; /* Resizing */ if (resize_area_grabbed) { resize_selection_rect (x, y); } /* Dragging the selection */ if (selection_grabbed) { selection_rect.x = (int) evt.x - drag_diff_x; selection_rect.y = (int) evt.y - drag_diff_y; /* Limit to image boundaries */ if (selection_rect.x < image_rect.x) selection_rect.x = image_rect.x; if (selection_rect.y < image_rect.y) selection_rect.y = image_rect.y; if (selection_rect.x + selection_rect.width > image_rect.x + image_rect.width) selection_rect.x = image_rect.x + image_rect.width - selection_rect.width; if (selection_rect.y + selection_rect.height > image_rect.y + image_rect.height) selection_rect.y = image_rect.y + image_rect.height - selection_rect.height; this.queue_draw (); return true; } if (over_resize_area (x, y) || resize_area_grabbed) { resize_area_hovered = true; set_cursor (resize_cursor); this.queue_draw (); return true; } else { set_cursor (default_cursor); resize_area_hovered = false; this.queue_draw (); } /* Check if cursor is over resize position */ if (cursor_in_selection (x, y)) { set_cursor (drag_cursor); } else { set_cursor (default_cursor); } return false; } private bool button_press_cb (Gdk.EventButton evt) { if (evt.button != Gdk.BUTTON_PRIMARY) { selection_grabbed = false; resize_area_grabbed = false; return false; } /* Check for the resize area(s) first */ if (over_resize_area (evt.x, evt.y)) { resize_area_grabbed = true; resize_diff_x = (int)evt.x - (selection_rect.x + selection_rect.width); resize_diff_y = (int)evt.y - (selection_rect.y + selection_rect.height); return true; } /* Now the selection rect */ if (cursor_in_selection (evt.x, evt.y)) { selection_grabbed = true; drag_diff_x = (int)(evt.x - selection_rect.x); drag_diff_y = (int)(evt.y - selection_rect.y); return true; } return false; } private bool button_release_cb (Gdk.EventButton evt) { if (selection_grabbed) { selection_grabbed = false; set_cursor (default_cursor); return true; } if (resize_area_grabbed) { resize_area_grabbed = false; set_cursor (default_cursor); return true; } return false; } private inline void restrict_selection_size () { if (selection_rect.width > image_rect.width) selection_rect.width = image_rect.width; if (selection_rect.height > image_rect.height) selection_rect.height = image_rect.height; if (selection_rect.width < (min_width * current_scale)) { selection_rect.width = (int)(min_width * current_scale); selection_rect.height = (int)(min_width * current_scale / desired_aspect_ratio); } if (selection_rect.x < image_rect.x) selection_rect.x = image_rect.x; if (selection_rect.y < image_rect.y) selection_rect.y = image_rect.y; if (selection_rect.x + selection_rect.width > image_rect.x + image_rect.width) selection_rect.x = image_rect.x + image_rect.width - selection_rect.width; if (selection_rect.y + selection_rect.height > image_rect.y + image_rect.height) selection_rect.y = image_rect.y + image_rect.height - selection_rect.height; } private void resize_selection_rect (double x, double y) { if (!resize_area_grabbed) return; int max_width = MIN (image_rect.width, MIN ((int)(image_rect.width), (int)(image_rect.height * desired_aspect_ratio))); int new_width = (int)x - selection_rect.x - resize_diff_x; int new_height = (int)(new_width / desired_aspect_ratio); if (new_width <= max_width) { selection_rect.width = new_width; selection_rect.height = new_height; } else { selection_rect.width = max_width; //message ("%d", selection_rect.width); //message ("%f", image_rect.width / desired_aspect_ratio); selection_rect.height = (int)(max_width / desired_aspect_ratio); } restrict_selection_size (); this.queue_draw (); } public void set_image (Gdk.Pixbuf image) { this.image = image; calculate_image_rect (); /* Place the selection rect initially, using the maximum size given the desired_aspect_ratio */ selection_rect.width = image_rect.width; selection_rect.height = (int)(selection_rect.width / desired_aspect_ratio); if (selection_rect.height > image_rect.height) { selection_rect.height = image_rect.height; selection_rect.width = (int)(selection_rect.height * desired_aspect_ratio); } selection_rect.x = image_rect.x + ((image_rect.width - selection_rect.width) / 2); selection_rect.y = image_rect.y + ((image_rect.height - selection_rect.height) / 2); restrict_selection_size (); this.queue_draw (); } public override bool draw (Cairo.Context ct) { if (image == null) return false; int widget_width = get_allocated_width (); int widget_height = get_allocated_height (); ct.set_line_width (1.0); /* Draw dark background */ ct.rectangle (0, 0, widget_width, widget_height); ct.set_source_rgba (0.3, 0.3, 0.3, 1.0); ct.fill (); /* Draw image */ ct.save (); ct.rectangle (image_rect.x, image_rect.y, image_rect.width, image_rect.height); ct.scale (current_scale, current_scale); Gdk.cairo_set_source_pixbuf (ct, image, image_rect.x / current_scale, image_rect.y / current_scale); ct.fill (); ct.restore (); /* Draw selection rectangle border */ ct.rectangle (selection_rect.x, selection_rect.y, selection_rect.width, selection_rect.height); ct.set_source_rgba (1.0, 1.0, 1.0, 1.0); ct.stroke (); /* Draw resize quad */ ct.rectangle (selection_rect.x + selection_rect.width - 15, selection_rect.y + selection_rect.height - 15, 14.5, 14.5); if (resize_area_hovered || resize_area_grabbed) ct.set_source_rgba (0.0, 0.0, 0.6, 0.7); else ct.set_source_rgba (1.0, 1.0, 1.0, 0.7); ct.fill (); return true; } private inline void set_cursor (Gdk.Cursor cursor) { this.get_window ().set_cursor (cursor); } private bool cursor_in_selection (double x, double y) { return x >= selection_rect.x && x <= selection_rect.x + selection_rect.width && y >= selection_rect.y && y <= selection_rect.y + selection_rect.height; } public override void size_allocate (Gtk.Allocation alloc) { base.size_allocate (alloc); calculate_image_rect (); restrict_selection_size (); } private void calculate_image_rect () { int widget_width = this.get_allocated_width (); int widget_height = this.get_allocated_height (); if (this.image == null) { return; } /* current_scale the image down */ if (image.get_width () > image.get_height ()) { current_scale = (double) widget_width / image.get_width (); } else { current_scale = (double) widget_height / image.get_height (); } if (image.get_width () * current_scale > widget_width) current_scale = (double) widget_width / image.get_width (); if (image.get_height () * current_scale > widget_height) current_scale = (double) widget_height / image.get_height (); /* Cap at 1.0 */ if (current_scale > 1.0) current_scale = 1.0; this.image_rect.width = (int)(this.image.get_width () * current_scale); this.image_rect.height = (int)(this.image.get_height () * current_scale); this.image_rect.x = (widget_width - image_rect.width) / 2; this.image_rect.y = (widget_height - image_rect.height) / 2; } private bool over_resize_area (double x, double y) { if (x > selection_rect.x + selection_rect.width - 15 && x < selection_rect.x + selection_rect.width + 5 && y > selection_rect.y + selection_rect.height - 15 && y < selection_rect.y + selection_rect.height + 5) { return true; } return false; } private inline int MIN (int a, int b) { if (a < b) return a; return b; } public Gdk.Pixbuf get_cropped_image () { int absolute_x = (int)((selection_rect.x - image_rect.x) / current_scale); int absolute_y = (int)((selection_rect.y - image_rect.y) / current_scale); int absolute_w = (int)(selection_rect.width / current_scale); int absolute_h = (int)(selection_rect.height / current_scale); Gdk.Pixbuf final_image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, this.image.get_has_alpha (), 8, absolute_w, absolute_h); this.image.copy_area (absolute_x, absolute_y, absolute_w, absolute_h, final_image, 0, 0); return final_image; } public void set_min_size (int min_width) { this.min_width = min_width; } } corebird-1.1/src/widgets/DMPlaceholderBox.vala000066400000000000000000000025221260276623600213750ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/dm-placeholder-box.ui")] class DMPlaceholderBox : Gtk.Box { [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label screen_name_label; public new string name { set { name_label.label = value; } } public string screen_name { set { screen_name_label.label = "@" + value; } } public string avatar_url; public void load_avatar () { avatar_image.surface = Twitter.get ().get_avatar (avatar_url, (a) => { avatar_image.surface = a; }); } } corebird-1.1/src/widgets/DoubleTapButton.vala000066400000000000000000000020171260276623600213330ustar00rootroot00000000000000 /* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class DoubleTapButton : Gtk.ToggleButton { private bool first_step = false; public void reset () { first_step = false; } public void tap () { if (!first_step) { first_step = true; return; } this.active = !this.active; first_step = false; } } corebird-1.1/src/widgets/FollowButton.vala000066400000000000000000000031451260276623600207210ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class FollowButton : Gtk.Button { private bool _following; public bool following { get { return _following; } set { var sc = this.get_style_context (); if (value) { sc.remove_class ("suggested-action"); sc.add_class ("destructive-action"); this.stack.visible_child = unfollow_label; } else { sc.remove_class ("destructive-action"); sc.add_class ("suggested-action"); this.stack.visible_child = follow_label; } this._following = value; } } private Gtk.Stack stack; private Gtk.Label follow_label; private Gtk.Label unfollow_label; construct { this.stack = new Gtk.Stack (); this.follow_label = new Gtk.Label (_("Follow")); this.unfollow_label = new Gtk.Label (_("Unfollow")); stack.add (follow_label); stack.add (unfollow_label); this.add (stack); } } corebird-1.1/src/widgets/ImpostorWidget.vala000066400000000000000000000032121260276623600212360ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class ImpostorWidget : Gtk.Image { private new Cairo.Surface surface; public ImpostorWidget () { this.halign = Gtk.Align.FILL; this.valign = Gtk.Align.FILL; } public override bool draw (Cairo.Context ct) { if (this.surface == null) return false; ct.set_source_surface (this.surface, 0, 0); ct.rectangle (0, 0, this.get_allocated_width (), this.get_allocated_height ()); ct.fill (); return false; } public void clone (Gtk.Widget widget) { int widget_width = widget.get_allocated_width (); int widget_height = widget.get_allocated_height (); this.surface = widget.get_window ().create_similar_surface (Cairo.Content.COLOR_ALPHA, widget_width, widget_height); var ct = new Cairo.Context (surface); widget.draw (ct); } } corebird-1.1/src/widgets/LazyMenuButton.vala000066400000000000000000000020021260276623600212120ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class LazyMenuButton : Gtk.ToggleButton { public GLib.Menu menu_model { get; set; } public override void clicked () { var popover = new Gtk.Popover.from_model (this, this.menu_model); popover.position = Gtk.PositionType.BOTTOM; popover.show (); } } corebird-1.1/src/widgets/MaxSizeContainer.vala000066400000000000000000000046041260276623600215070ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class MaxSizeContainer : Gtk.Bin { private int _max_size = 0; public int max_size { get { return this._max_size; } set { this._max_size = value; this.queue_resize (); } } public override Gtk.SizeRequestMode get_request_mode () { return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; } public override void get_preferred_height_for_width (int width, out int min_height, out int nat_height) { int child_height; get_child ().get_preferred_height_for_width (width, out child_height, null); if (max_size >= child_height) { base.get_preferred_height_for_width (width, out min_height, out nat_height); } else { nat_height = max_size; min_height = max_size; } } public override void size_allocate (Gtk.Allocation alloc) { if (get_child () == null || !get_child ().visible) return; Gtk.Allocation child_alloc = {}; child_alloc.x = alloc.x; child_alloc.width = alloc.width; if (max_size >= alloc.height) { // We don't cut away anything child_alloc.y = alloc.y; child_alloc.height = alloc.height; } else { child_alloc.y = alloc.y;// - (max_size - alloc.height); child_alloc.height = max_size; } base.size_allocate (child_alloc); if (get_child () != null && get_child ().visible) { get_child ().size_allocate (child_alloc); if (this.get_realized ()) get_child ().show (); } if (this.get_realized ()) { if (get_child () != null) get_child ().set_child_visible (true); } } } corebird-1.1/src/widgets/MediaImageWidget.vala000066400000000000000000000111141260276623600214040ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class MediaImageWidget : Gtk.ScrolledWindow { private Gtk.Image image; private Gtk.Menu image_context_menu; private new string path; private double dnd_x; private double dnd_y; public MediaImageWidget (string path) { this.path = path; this.button_press_event.connect (button_press_event_cb); this.image = new Gtk.Image (); Gtk.EventBox event_box = new Gtk.EventBox (); event_box.add (this.image); event_box.motion_notify_event.connect (event_box_motion_notify_cb); event_box.button_press_event.connect (event_box_button_press_cb); this.add (event_box); image_context_menu = new Gtk.Menu (); var save_as_item = new Gtk.MenuItem (); save_as_item.label = _("Save Image"); save_as_item.activate.connect (save_item_activated_cb); save_as_item.show (); image_context_menu.add (save_as_item); //Choose proper width/height Gdk.Pixbuf? pixbuf = null; try { pixbuf = new Gdk.Pixbuf.from_file(path); } catch (GLib.Error e) { critical(e.message); } try { if(path.has_suffix("gif")) image.pixbuf_animation = new Gdk.PixbufAnimation.from_file(path); else image.pixbuf = new Gdk.Pixbuf.from_file(path); } catch (GLib.Error e) { critical (e.message); return; } int img_width = pixbuf.get_width(); int img_height = pixbuf.get_height(); int win_width = 800; int win_height = 600; if(img_width <= Gdk.Screen.width()*0.7) { win_width = img_width; this.hscrollbar_policy = Gtk.PolicyType.NEVER; } if(img_height <= Gdk.Screen.height()*0.7) { win_height = img_height; this.vscrollbar_policy = Gtk.PolicyType.NEVER; } if(win_width < 800 && win_height == 600) { int add_width; this.get_vscrollbar().get_preferred_width(null, out add_width); win_width += add_width; } if(win_width == 800 && win_height < 600) { int add_height; this.get_hscrollbar().get_preferred_width(null, out add_height); win_height += add_height; } this.set_size_request(win_width, win_height); } private bool event_box_motion_notify_cb (Gdk.EventMotion evt) { if ((evt.state & Gdk.ModifierType.MODIFIER_MASK) >= Gdk.ModifierType.BUTTON2_MASK) { double diff_x = dnd_x - evt.x; double diff_y = dnd_y - evt.y; this.vadjustment.value += diff_y; this.hadjustment.value += diff_x; return true; } return false; } private bool event_box_button_press_cb (Gdk.EventButton evt) { if (evt.button == 2) { this.dnd_x = evt.x; this.dnd_y = evt.y; return true; } return false; } private void save_item_activated_cb () { var file_dialog = new Gtk.FileChooserDialog (_("Save image"), null, Gtk.FileChooserAction.SAVE, _("Cancel"), Gtk.ResponseType.CANCEL, _("Save"), Gtk.ResponseType.ACCEPT); string filename = Utils.get_file_name (path); file_dialog.set_current_name (filename); //file_dialog.set_transient_for (this); int response = file_dialog.run (); if (response == Gtk.ResponseType.ACCEPT) { File dest = File.new_for_uri (file_dialog.get_uri ()); debug ("Source: %s", path); debug ("Destin: %s", file_dialog.get_uri ()); File source = File.new_for_path (path); try { source.copy (dest, FileCopyFlags.OVERWRITE); } catch (GLib.Error e) { critical (e.message); } file_dialog.destroy (); } else if (response == Gtk.ResponseType.CANCEL) file_dialog.destroy (); } private bool button_press_event_cb (Gdk.EventButton evt) { if (evt.button == 3) { image_context_menu.popup (null, null, null, evt.button, evt.time); return true; } return false; } } corebird-1.1/src/widgets/MediaVideoWidget.vala000066400000000000000000000144641260276623600214430ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class MediaVideoWidget : Gtk.Stack { #if VIDEO private Gst.Element src; private Gst.Element sink; private uint *xid; #endif private Gtk.ProgressBar progress_bar = new Gtk.ProgressBar (); private Gtk.DrawingArea drawing_area = new Gtk.DrawingArea (); private int64 file_content_length = -1; private int64 current_content_length = 0; private GLib.Cancellable cancellable; private Gtk.Label error_label = new Gtk.Label (""); public MediaVideoWidget (Media media) { this.cancellable = new GLib.Cancellable (); drawing_area.realize.connect (realize_cb); #if VIDEO this.src = Gst.ElementFactory.make ("playbin", "video"); this.sink = Gst.ElementFactory.make ("xvimagesink", "sink"); this.src.set ("video-sink", sink, null); var bus = src.get_bus (); bus.set_sync_handler (bus_sync_handler); bus.add_watch (GLib.Priority.DEFAULT, watch_cb); if (media.type == MediaType.VINE) fetch_real_url.begin (media.url, " { SOUP_SESSION.cancel_message (msg, Soup.Status.CANCELLED); }); SOUP_SESSION.queue_message (msg, (s, _msg) => { if (_msg.status_code != Soup.Status.OK) { if (_msg.status_code != Soup.Status.CANCELLED) { warning ("Status Code %u", _msg.status_code); show_error ("%u %s".printf (_msg.status_code, Soup.Status.get_phrase (_msg.status_code))); } fetch_real_url.callback (); return; } string back = (string)_msg.response_body.data; try { var regex = new GLib.Regex (regex_str, 0); MatchInfo info; regex.match (back, 0, out info); string? real_url = info.fetch (1); if (real_url == null) { show_error ("Error: Could not get real URL"); } else download_video.begin (real_url); } catch (GLib.RegexError e) { warning ("Regex error: %s", e.message); show_error ("Regex error: %s".printf (e.message)); } fetch_real_url.callback (); }); yield; } // }}} private async void download_video (string url) { var msg = new Soup.Message ("GET", url); msg.got_headers.connect (() => { file_content_length = msg.response_headers.get_content_length (); }); cancellable.cancelled.connect (() => { SOUP_SESSION.cancel_message (msg, Soup.Status.CANCELLED); }); msg.got_chunk.connect ((buffer) => { current_content_length += buffer.length; double fraction = (double) current_content_length / (double) file_content_length; progress_bar.fraction = fraction; progress_bar.text = "%d %%".printf ((int)(fraction * 100)); }); SOUP_SESSION.queue_message (msg, (s, _msg) => { if (_msg.status_code != Soup.Status.OK) { if (_msg.status_code != Soup.Status.CANCELLED) { warning ("Status Code %u", _msg.status_code); show_error ("%u %s".printf (_msg.status_code, Soup.Status.get_phrase (_msg.status_code))); } download_video.callback (); return; } #if VIDEO string b64 = GLib.Base64.encode ((uchar[])msg.response_body.data); var sa = "data:;base64," + b64; this.src.set ("uri", sa); this.visible_child_name = "video"; src.set_state (Gst.State.PLAYING); #endif download_video.callback (); }); yield; } } corebird-1.1/src/widgets/MultiMediaWidget.vala000066400000000000000000000207531260276623600214650ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ // TODO: Allow D'n'D out of the button private class MediaButton : Gtk.Button { private unowned Media? _media; private static Cairo.Surface[] play_icons; private static const int PLAY_ICON_SIZE = 32; public unowned Media? media { get { return _media; } set { _media = value; if (value != null) { _media.notify["percent-loaded"].connect (this.queue_draw); } if (value != null && (value.type == MediaType.IMAGE || value.type == MediaType.GIF)) { menu_model.append (_("Copy URL"), "media.copy-url"); menu_model.append (_("Save Original"), "media.save-original"); } } } public unowned Gtk.Window window; private GLib.Menu menu_model; private Gtk.Menu menu; private GLib.SimpleActionGroup actions; private const GLib.ActionEntry[] action_entries = { {"copy-url", copy_url_activated}, {"save-original", save_original_activated}, {"open-in-browser", open_in_browser_activated} }; private Pango.Layout layout; static construct { try { play_icons = { Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/play.png"), 1, null), Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/play@2.png"), 2, null), }; } catch (GLib.Error e) { critical (e.message); } } public MediaButton (Media? media) { this.media = media; this.set_size_request (-1, MultiMediaWidget.HEIGHT); this.get_style_context ().add_class ("inline-media"); this.get_style_context ().add_class ("dim-label"); actions = new GLib.SimpleActionGroup (); actions.add_action_entries (action_entries, this); this.insert_action_group ("media", actions); this.menu_model = new GLib.Menu (); menu_model.append (_("Open in Browser"), "media.open-in-browser"); this.menu = new Gtk.Menu.from_model (menu_model); this.menu.attach_to_widget (this, null); this.layout = this.create_pango_layout ("0%"); this.button_press_event.connect (button_clicked_cb); } public override bool draw (Cairo.Context ct) { int widget_width = get_allocated_width (); int widget_height = get_allocated_height (); /* Draw thumbnail */ if (media != null && media.thumbnail != null && media.loaded) { ct.save (); ct.rectangle (0, 0, widget_width, widget_height); double scale = (double)widget_width / ((Cairo.ImageSurface)media.thumbnail).get_width (); ct.scale (scale, 1); ct.set_source_surface (media.thumbnail, 0, 0); ct.fill (); ct.restore (); /* Draw play indicator */ if (media.type == MediaType.VINE || media.type == MediaType.ANIMATED_GIF || media.type == MediaType.GIF || media.type == MediaType.TWITTER_VIDEO) { int x = (widget_width / 2) - (PLAY_ICON_SIZE / 2); int y = (widget_height / 2) - (PLAY_ICON_SIZE / 2); ct.rectangle (x, y, PLAY_ICON_SIZE, PLAY_ICON_SIZE); ct.set_source_surface (play_icons[this.get_scale_factor () - 1], x, y); ct.fill (); } } else { var sc = this.get_style_context (); double layout_x, layout_y; int layout_w, layout_h; layout.set_text ("%d%%".printf ((int)(media.percent_loaded * 100)), -1); layout.get_size (out layout_w, out layout_h); layout_x = (widget_width / 2.0) - (layout_w / Pango.SCALE / 2.0); layout_y = (widget_height / 2.0) - (layout_h / Pango.SCALE / 2.0); sc.render_layout (ct, layout_x, layout_y, layout); } return base.draw (ct); } private bool button_clicked_cb (Gdk.EventButton evt) { if (evt.button == Gdk.BUTTON_SECONDARY && this.media != null) { menu.show_all (); menu.popup (null, null, null, evt.button, evt.time); return true; } return false; } private void copy_url_activated (GLib.SimpleAction a, GLib.Variant? v) { Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (Gdk.Display.get_default (), Gdk.SELECTION_CLIPBOARD); clipboard.set_text (media.url, -1); } private void open_in_browser_activated (GLib.SimpleAction a, GLib.Variant? v) { try { Gtk.show_uri (Gdk.Screen.get_default (), media.target_url, Gtk.get_current_event_time ()); } catch (GLib.Error e) { critical (e.message); } } private void save_original_activated (GLib.SimpleAction a, GLib.Variant? v) { var file_dialog = new Gtk.FileChooserDialog (_("Save image"), window, Gtk.FileChooserAction.SAVE, _("Cancel"), Gtk.ResponseType.CANCEL, _("Save"), Gtk.ResponseType.ACCEPT); string filename = Utils.get_file_name (media.path); file_dialog.set_current_name (filename); file_dialog.set_transient_for (window); int response = file_dialog.run (); if (response == Gtk.ResponseType.ACCEPT) { File dest = File.new_for_uri (file_dialog.get_uri ()); File source = File.new_for_path (media.path); try { source.copy (dest, FileCopyFlags.OVERWRITE); } catch (GLib.Error e) { critical (e.message); } file_dialog.destroy (); } else if (response == Gtk.ResponseType.CANCEL) file_dialog.destroy (); } } public class MultiMediaWidget : Gtk.Box { public static const int HEIGHT = 60; public int media_count { public get; private set; default = 0;} public unowned Gtk.Window window; private MediaButton[] media_buttons; public signal void media_clicked (Media m, int index); private bool media_invalid_fired = false; public signal void media_invalid (); public MultiMediaWidget (int media_count) { this.media_count = media_count; this.media_buttons = new MediaButton[media_count]; } public void set_all_media (Media[] medias) { this.remove_all (); this.media_buttons = new MediaButton[medias.length]; this.media_count = medias.length; for (int i = 0; i < medias.length; i++) { assert (medias[i] != null); set_media (i, medias[i]); } } private void remove_all () { this.get_children ().foreach ((w) => { this.remove (w); }); } public void set_media (int index, Media media) { assert (index < media_count); if (media.loaded && media.invalid) return; var button = new MediaButton (null); button.set_data ("pos", index); button.window = this.window; media_buttons[index] = button; if (media.loaded) { media_buttons[index].media = media; } else { media_buttons[index].media = media; media.finished_loading.connect (media_loaded_cb); } button.visible = true; button.clicked.connect (button_clicked_cb); this.pack_start (button, true, true); this.queue_draw (); } private void button_clicked_cb (Gtk.Button source) { var mb = (MediaButton)source; if (mb.media != null && mb.media.loaded) { int index = mb.get_data ("pos"); media_clicked (mb.media, index); } } private void media_loaded_cb (Media source) { if (source.invalid) { for (int i = 0; i < media_count; i ++) { if (media_buttons[i] != null && media_buttons[i].media == source) { this.remove (media_buttons[i]); media_buttons[i] = null; if (!media_invalid_fired) { media_invalid (); media_invalid_fired = true; } return; } } } for (int i = 0; i < media_count; i ++) { if (media_buttons[i] != null && media_buttons[i].media == source) { media_buttons[i].queue_draw (); break; } } } } corebird-1.1/src/widgets/PixbufButton.vala000066400000000000000000000075161260276623600207220ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class PixbufButton : Gtk.Button { private Cairo.ImageSurface bg; private Gtk.Menu menu; private string menu_string; private bool _round = false; public bool round { get { return _round; } set { if (value) { this.get_style_context ().add_class ("pixbuf-button-round"); } else { this.get_style_context ().remove_class ("pixbuf-button-round"); } _round = value; } } construct { this.border_width = 0; get_style_context ().add_class ("pixbuf-button"); } public PixbufButton (bool show_menu = false, string? menu_string = null) { if (show_menu) { this.button_press_event.connect (button_release_cb); this.menu_string = menu_string; } } private bool button_release_cb (Gdk.EventButton evt) { if (evt.button == Gdk.BUTTON_SECONDARY) { menu = new Gtk.Menu (); var source_link_item = new Gtk.MenuItem.with_label (_("Copy link")); source_link_item.activate.connect (source_link_item_activate_cb); menu.add (source_link_item); menu.show_all (); menu.popup (null, null, null, evt.button, evt.time); return true; } return false; } private void source_link_item_activate_cb () { Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (Gdk.Display.get_default (), Gdk.SELECTION_CLIPBOARD); clipboard.set_text (menu_string, -1); } public override bool draw (Cairo.Context ct) { var sc = this.get_style_context (); int widget_width = this.get_allocated_width (); int widget_height = this.get_allocated_height (); if (bg != null) { var surface = new Cairo.Surface.similar (ct.get_target (), Cairo.Content.COLOR_ALPHA, widget_width, widget_height); var ctx = new Cairo.Context (surface); ctx.rectangle (0, 0, widget_width, widget_height); double scale_x = (double)widget_width / bg.get_width (); double scale_y = (double)widget_height / bg.get_height (); ctx.save (); ctx.scale (scale_x, scale_y); ctx.set_source_surface (bg, 0, 0); ctx.fill (); ctx.restore (); if (_round) { // make it round ctx.set_operator (Cairo.Operator.DEST_IN); ctx.translate (widget_width / 2, widget_height / 2); ctx.arc (0, 0, widget_width / 2, 0, 2 * Math.PI); ctx.fill (); // draw outline sc.render_frame (ct, 0, 0, widget_width, widget_height); } ct.rectangle (0, 0, widget_width, widget_height); ct.set_source_surface (surface, 0, 0); ct.fill (); } // The css-styled background should be transparent. base.draw (ct); return GLib.Source.CONTINUE; } public void set_bg (Cairo.ImageSurface bg) { this.bg = bg; this.set_size_request (bg.get_width(), bg.get_height()); this.queue_draw (); } public void set_pixbuf (Gdk.Pixbuf pixbuf) { this.bg = (Cairo.ImageSurface)Gdk.cairo_surface_create_from_pixbuf (pixbuf, 1, null); this.queue_draw (); } } corebird-1.1/src/widgets/ReplyEntry.vala000066400000000000000000000021261260276623600203760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class ReplyEntry : Gtk.Entry { [Signal (action = true)] public signal void cancelled (); public ReplyEntry () {} static construct { unowned Gtk.BindingSet binding_set = Gtk.BindingSet.by_class ((GLib.ObjectClass)typeof (ReplyEntry).class_ref ()); Gtk.BindingEntry.add_signal (binding_set, Gdk.Key.Escape, 0, "cancelled", 0, null); } } corebird-1.1/src/widgets/ReplyIndicator.vala000066400000000000000000000053641260276623600212200ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class ReplyIndicator : Gtk.Widget { private static const int FINAL_HEIGHT = 5; private double height = 0; private bool replies = false; public bool replies_available { set { this.replies = value; this.on_replies_available (); } get { return replies; } } private int64 start_time; construct { set_has_window (false); get_style_context ().add_class ("reply-indicator"); } public override Gtk.SizeRequestMode get_request_mode () { return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; } public override void get_preferred_height_for_width (int width, out int min_height, out int nat_height) { min_height = FINAL_HEIGHT; nat_height = FINAL_HEIGHT; } private void on_replies_available () { if (!replies) { height = 0.0; return; } start_time = this.get_frame_clock ().get_frame_time (); this.add_tick_callback (tick_callback); } private bool tick_callback (Gtk.Widget widget, Gdk.FrameClock frame_clock) { if (!this.get_mapped ()) { height = FINAL_HEIGHT; this.queue_draw (); return false; } int64 now = frame_clock.get_frame_time (); int64 end_time = this.start_time + (750 * 1000); /* .75s */ double t = 1.0; if (now < end_time) t = (now - start_time) / (double)(end_time - start_time); t = ease_out_cubic (t); height = t * FINAL_HEIGHT; if (height >= FINAL_HEIGHT) { height = FINAL_HEIGHT; this.queue_draw (); return false; } this.queue_draw (); return true; } private double ease_out_cubic (double t) { double p = t - 1; return p * p * p +1; } public override bool draw (Cairo.Context ct) { if (!replies) { return false; } var style_context = this.get_style_context (); int width = this.get_allocated_width (); style_context.render_background (ct, 0, 0, width, height); return false; } } corebird-1.1/src/widgets/ScrollWidget.vala000066400000000000000000000160431260276623600206660ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ const int TOP = 1; const int BOTTOM = 2; const int NONE = 0; public class ScrollWidget : Gtk.ScrolledWindow { private static const int64 TRANSITION_DURATION = 300; public signal void scrolled_to_start(double value); public signal void scrolled_to_end(); private double upper_cache; private double value_cache; private int balance = NONE; public double end_diff {get; set; default = 200;} private ulong scroll_down_id; private ulong scroll_up_id; public bool scrolled_down { get { return vadjustment.value >= vadjustment.upper - vadjustment.page_size - 5; } } public bool scrolled_up { get { return vadjustment.value <= 5; } } //Transition times private int64 start_time; private int64 end_time; private double transition_diff; private double transition_start_value; construct { vadjustment.notify["upper"].connect (keep_upper_func); vadjustment.notify["value"].connect (keep_value_func); } private void keep_upper_func() { // {{{ double upper = vadjustment.upper; if (balance == TOP){ double inc = (upper - upper_cache); this.vadjustment.value += inc; this.vadjustment.value_changed (); balance = NONE; } this.upper_cache = vadjustment.upper; this.value_cache = vadjustment.value; } // }}} private void keep_value_func () { // {{{ // Call the scrolled_to_top signal if necessary if(vadjustment.value < 10.0) { scrolled_to_start(vadjustment.value); } double max = vadjustment.upper - vadjustment.page_size; if (vadjustment.value >= max - end_diff) scrolled_to_end (); double upper = vadjustment.upper; if (balance == BOTTOM) { double inc = (upper - upper_cache); this.vadjustment.value -= inc; this.vadjustment.value_changed (); balance = NONE; } this.upper_cache = vadjustment.upper; this.value_cache = vadjustment.value; } // }}} public void balance_next_upper_change (int mode) { balance = mode; } /** * TODO: Update scroll_down_next * Scroll to the very top of the scrolled window once the next * size_allocate occurs. * This will use a transition if the correct Gtk+ settings is set * to true. * * @param animate Whether to animate/transition the change or not (default: true) * @param force_wait If this is set to true, we will wait for the next size_allocate * event, even if the widget is unmapped (default: false). */ public void scroll_up_next (bool animate = true, bool force_wait = false, bool force_start = false) { // {{{ if (!this.get_mapped () && !force_wait) { this.vadjustment.value = 0; this.vadjustment.value_changed (); return; } // TODO: I really can't stand the duplication here if (force_start) { if (Gtk.Settings.get_default ().gtk_enable_animations && animate) { this.start_time = this.get_frame_clock ().get_frame_time (); this.end_time = start_time + (TRANSITION_DURATION * 1000); this.transition_diff = - this.vadjustment.value; this.transition_start_value = vadjustment.value; this.add_tick_callback (scroll_up_tick_cb); } else { this.vadjustment.value = 0; this.vadjustment.value_changed (); } } else { if (scroll_up_id != 0) { this.transition_diff = -this.vadjustment.value; this.transition_start_value = this.vadjustment.value; return; } scroll_up_id = this.size_allocate.connect (() => { if (Gtk.Settings.get_default ().gtk_enable_animations && animate) { this.start_time = this.get_frame_clock ().get_frame_time (); this.end_time = start_time + (TRANSITION_DURATION * 1000); this.transition_diff = - this.vadjustment.value; this.transition_start_value = vadjustment.value; this.add_tick_callback (scroll_up_tick_cb); } else { this.vadjustment.value = 0; this.vadjustment.value_changed (); } this.disconnect (scroll_up_id); this.scroll_up_id = 0; }); } } // }}} /** * Scroll to the very end of the scrolled window once the next * size_alocate occurs. * This will use a transition if the correct Gtk+ settings is set * to true * * @param animate Whether to animate/transition the change or not (default: true) * @param force_wait If this is set to true, we will wait for the next size_allocate * event, even if the widget is unmapped (default: false). */ public void scroll_down_next (bool animate = true, bool force_wait = false) { // {{{ if (!this.get_mapped () && !force_wait) { this.vadjustment.value = this.vadjustment.upper - this.vadjustment.page_size; this.vadjustment.value_changed (); return; } if (this.scroll_down_id != 0) return; scroll_down_id = this.size_allocate.connect (() => { if (Gtk.Settings.get_default ().gtk_enable_animations && animate) { this.start_time = this.get_frame_clock ().get_frame_time (); this.end_time = start_time + (TRANSITION_DURATION * 1000); this.transition_diff = (vadjustment.upper - vadjustment.page_size - vadjustment.value); this.transition_start_value = this.vadjustment.value; this.add_tick_callback (scroll_up_tick_cb); } else { this.vadjustment.value = this.vadjustment.upper - this.vadjustment.page_size; this.vadjustment.value_changed (); } this.disconnect (scroll_down_id); this.scroll_down_id = 0; }); } // }}} /* This is essentially a straight-up vala port of the transition code in GtkStack/GtkRevealer */ private bool scroll_up_tick_cb (Gtk.Widget widget, Gdk.FrameClock frame_clock) { if (!this.get_mapped ()) { vadjustment.value = transition_start_value + transition_diff; return false; } int64 now = frame_clock.get_frame_time (); double t = 1.0; if (now < this.end_time) t = (now - start_time) / (double)(end_time - start_time); t = ease_out_cubic (t); this.vadjustment.value = transition_start_value + (t * transition_diff); if (this.vadjustment.value <= 0 || now >= end_time) return false; return true; } private double ease_out_cubic (double t) { double p = t - 1; return p * p * p +1; } } corebird-1.1/src/widgets/TextButton.vala000066400000000000000000000040601260276623600204000ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class TextButton : Gtk.Button { public bool read_only { set { if (value) { this.get_style_context ().add_class ("readonly-text-only-button"); } else { this.get_style_context ().remove_class ("readonly-text-only-button"); } this.sensitive = !value; } } public TextButton (string label = "") { if (label != "") this.label= label; this.get_style_context ().add_class ("text-only-button"); } /** * Adds a GtkLabel to the Button using the given text as markup. * If the button already contains another child, that will either be replaced if it's * no instance of GtkLabel, or - if it's a GtkLabel already - be reused. * * @param text The markup to use(see pango markup) */ public void set_markup (string text) { Gtk.Label label = null; Gtk.Widget child = get_child (); if (child != null) { if (child is Gtk.Label) { label = (Gtk.Label)child; label.set_markup (text); } else { this.remove (child); label = new Gtk.Label (text); } } else { label = new Gtk.Label (text); } label.set_use_markup (true); label.set_justify (Gtk.Justification.CENTER); label.valign = Gtk.Align.BASELINE; label.visible = true; if(label.parent == null) this.add (label); } } corebird-1.1/src/widgets/TweetListBox.vala000066400000000000000000000120531260276623600206560ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class TweetListBox : Gtk.ListBox { private Gtk.Stack placeholder; private Gtk.Label no_entries_label; private Gtk.Box error_box; private Gtk.Label error_label; private Gtk.Button retry_button; private TweetListEntry? _action_entry; public TweetListEntry? action_entry { get { return _action_entry; } } public signal void retry_button_clicked (); public unowned DeltaUpdater delta_updater; public unowned Account account; public TweetModel model = new TweetModel (); public TweetListBox (bool show_placeholder = true) { if (show_placeholder) { add_placeholder (); } } construct { add_placeholder (); this.get_style_context ().add_class ("stream"); this.set_selection_mode (Gtk.SelectionMode.NONE); this.button_press_event.connect (button_press_cb); Settings.get ().bind ("double-click-activation", this, "activate-on-single-click", GLib.SettingsBindFlags.INVERT_BOOLEAN); this.bind_model (this.model, (obj) => { assert (obj is Tweet); var row = new TweetListEntry ((Tweet) obj, (MainWindow) get_toplevel (), this.account); delta_updater.add (row); row.fade_in (); return row; }); } private bool button_press_cb (Gdk.EventButton evt) { if (evt.triggers_context_menu ()) { /* From gtklistbox.c */ Gdk.Window? event_window = evt.window; Gdk.Window window = this.get_window (); double relative_y = evt.y; double parent_y; while ((event_window != null) && (event_window != window)) { event_window.coords_to_parent (0, relative_y, null, out parent_y); relative_y = parent_y; event_window = event_window.get_effective_parent (); } Gtk.Widget row = this.get_row_at_y ((int)relative_y); if (row is TweetListEntry && row.sensitive) { var tle = (TweetListEntry) row; if (tle != this._action_entry && this._action_entry != null && this._action_entry.shows_actions) { this._action_entry.toggle_mode (); } tle.toggle_mode (); if (tle.shows_actions) this._action_entry = tle; else this._action_entry = null; return true; } } return false; } private void add_placeholder () { placeholder = new Gtk.Stack (); placeholder.transition_type = Gtk.StackTransitionType.CROSSFADE; var loading_label = new Gtk.Label (_("Loading...")); loading_label.get_style_context ().add_class ("dim-label"); placeholder.add_named (loading_label, "spinner"); no_entries_label = new Gtk.Label (_("No entries found")); no_entries_label.get_style_context ().add_class ("dim-label"); no_entries_label.wrap_mode = Pango.WrapMode.WORD_CHAR; placeholder.add_named (no_entries_label, "no-entries"); error_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); error_label = new Gtk.Label (""); error_label.get_style_context ().add_class ("dim-label"); retry_button = new Gtk.Button.with_label (_("Retry")); retry_button.set_halign (Gtk.Align.CENTER); retry_button.clicked.connect (() => { placeholder.visible_child_name = "spinner"; retry_button_clicked (); }); error_box.add (error_label); error_box.add (retry_button); placeholder.add_named (error_box, "error"); placeholder.visible_child_name = "spinner"; placeholder.show_all (); placeholder.set_valign (Gtk.Align.CENTER); placeholder.set_halign (Gtk.Align.CENTER); this.set_placeholder (placeholder); } public void set_empty () { placeholder.visible_child_name = "no-entries"; } public void set_unempty () { placeholder.visible_child_name = "spinner"; } public void set_error (string err_msg) { error_label.label = err_msg; placeholder.visible_child_name = "error"; } public Gtk.Stack? get_placeholder () { return placeholder; } public void set_placeholder_text (string text) { no_entries_label.label = text; } public void reset_placeholder_text () { no_entries_label.label = _("No entries found"); } public void remove_all () { this.foreach ((w) => { remove (w); }); } public Gtk.Widget? get_first_visible_row () { return this.get_row_at_y (1); } } corebird-1.1/src/widgets/UserListsWidget.vala000066400000000000000000000226151260276623600213670ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/user-lists-widget.ui")] class UserListsWidget : Gtk.Box { [GtkChild] private Gtk.Label user_list_label; [GtkChild] private Gtk.ListBox user_list_box; [GtkChild] private Gtk.Frame user_list_frame; [GtkChild] private Gtk.Label subscribed_list_label; [GtkChild] private Gtk.ListBox subscribed_list_box; [GtkChild] private Gtk.Frame subscribed_list_frame; [GtkChild] private NewListEntry new_list_entry; public unowned MainWindow main_window { get; set; } public unowned Account account { get; set; } private bool show_create_entry = true; construct { user_list_box.set_header_func (default_header_func); user_list_box.set_sort_func (ListListEntry.sort_func); subscribed_list_box.set_header_func (default_header_func); subscribed_list_box.set_sort_func (ListListEntry.sort_func); } public void hide_user_list_entry () { new_list_entry.hide (); new_list_entry.no_show_all = true; user_list_label.visible = true; //user_list_frame.margin_top = 24; show_create_entry = false; } [GtkCallback] private void row_activated (Gtk.ListBoxRow row) { if (row is NewListEntry) { ((NewListEntry)row).reveal (); } else { var entry = (ListListEntry) row; var bundle = new Bundle (); bundle.put_int64 ("list_id", entry.id); bundle.put_string ("name", entry.name); bundle.put_bool ("user_list", entry.user_list); bundle.put_string ("description", entry.description); bundle.put_string ("creator", entry.creator_screen_name); bundle.put_int ("n_subscribers", entry.n_subscribers); bundle.put_int ("n_members", entry.n_members); bundle.put_int64 ("created_at", entry.created_at); bundle.put_string ("mode", entry.mode); main_window.main_widget.switch_page (Page.LIST_STATUSES, bundle); } } public async void load_lists (int64 user_id) { // {{{ if (user_id == 0) user_id = account.id; var collect_obj = new Collect (2); var call = account.proxy.new_call (); call.set_function ("1.1/lists/subscriptions.json"); call.set_method ("GET"); call.add_param ("user_id", user_id.to_string ()); TweetUtils.load_threaded.begin (call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); } uint n_subscribed_list = lists_received_cb (root, subscribed_list_box); if (n_subscribed_list == 0) { subscribed_list_box.hide (); subscribed_list_frame.hide (); subscribed_list_label.hide (); } else { subscribed_list_box.show (); subscribed_list_frame.show (); subscribed_list_label.show (); } collect_obj.emit (); }); var user_call = account.proxy.new_call (); user_call.set_function ("1.1/lists/ownerships.json"); user_call.set_method ("GET"); user_call.add_param ("user_id", user_id.to_string ()); TweetUtils.load_threaded.begin (user_call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); } uint n_user_list = lists_received_cb (root, user_list_box); if (n_user_list == 0 && !show_create_entry) { user_list_label.hide (); user_list_box.hide (); user_list_frame.hide (); user_list_frame.margin_top = 0; } else { user_list_label.visible = !show_create_entry; user_list_frame.margin_top = show_create_entry ? 24 : 0; user_list_box.show (); user_list_frame.show (); } collect_obj.emit (); }); collect_obj.finished.connect (() => { load_lists.callback (); }); yield; } // }}} private uint lists_received_cb (Json.Node? root, Gtk.ListBox list_box) { // {{{ if (root == null) return 0; var arr = root.get_object ().get_array_member ("lists"); arr.foreach_element ((array, index, node) => { var obj = node.get_object (); var entry = new ListListEntry.from_json_data (obj, account); list_box.add (entry); }); return arr.get_length (); } // }}} public void remove_list (int64 list_id) { user_list_box.foreach ((w) => { if (!(w is ListListEntry)) return; if (((ListListEntry)w).id == list_id) { user_list_box.remove (w); } }); subscribed_list_box.foreach ((w) => { if (!(w is ListListEntry)) return; if (((ListListEntry)w).id == list_id) { subscribed_list_box.remove (w); } }); if (subscribed_list_box.get_children ().length () == 0) { subscribed_list_label.hide (); subscribed_list_frame.hide (); } } public void add_list (ListListEntry entry) { if (entry.user_list) { // Avoid duplicates var user_lists = user_list_box.get_children (); foreach (Gtk.Widget w in user_lists) { if (!(w is ListListEntry)) continue; if (((ListListEntry)w).id == entry.id) return; } user_list_box.add (entry); } else { // Avoid duplicates var subscribed_lists = subscribed_list_box.get_children (); foreach (Gtk.Widget w in subscribed_lists) { if (!(w is ListListEntry)) continue; if (((ListListEntry)w).id == entry.id) return; } subscribed_list_box.add (entry); subscribed_list_frame.show (); subscribed_list_box.show (); subscribed_list_label.show (); } } public void update_list (int64 list_id, string name, string description, string mode) { user_list_box.foreach ((w) => { if (!(w is ListListEntry)) return; var lle = (ListListEntry) w; if (lle.id == list_id) { lle.name = name; lle.description = description; lle.mode = mode; lle.queue_draw (); } }); } public void update_member_count (int64 list_id, int increase) { var lists = user_list_box.get_children (); foreach (var list in lists) { if (!(list is ListListEntry)) continue; var lle = (ListListEntry) list; if (lle.id == list_id) { lle.n_members += increase; break; } } } public TwitterList[] get_user_lists () { // {{{ GLib.List children = user_list_box.get_children (); TwitterList[] lists = new TwitterList[children.length () - 1]; int i = 0; foreach (Gtk.Widget w in children) { if (!(w is ListListEntry)) continue; var lle = (ListListEntry) w; lists[i].id = lle.id; lists[i].name = lle.name; lists[i].description = lle.description; lists[i].mode = lle.mode; lists[i].n_members = lle.n_members; i ++; } return lists; } // }}} public void clear_lists () { user_list_box.foreach ((w) => { user_list_box.remove (w);}); subscribed_list_box.foreach ((w) => {subscribed_list_box.remove (w);}); } [GtkCallback] private void new_list_create_activated_cb (string list_name) { // {{{ if (list_name.strip ().length <= 0) return; new_list_entry.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/lists/create.json"); call.set_method ("POST"); call.add_param ("name", list_name); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); new_list_entry.sensitive = true; return; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical (e.message); return; } var root = parser.get_root ().get_object (); var entry = new ListListEntry.from_json_data (root, account); add_list (entry); var bundle = new Bundle (); bundle.put_int64 ("list_id", entry.id); bundle.put_string ("name", entry.name); bundle.put_bool ("user_list", true); bundle.put_string ("description", entry.description); bundle.put_string ("creator", entry.creator_screen_name); bundle.put_int ("n_subscribers", entry.n_subscribers); bundle.put_int ("n_members", entry.n_members); bundle.put_int64 ("created_at", entry.created_at); bundle.put_string ("mode", entry.mode); main_window.main_widget.switch_page (Page.LIST_STATUSES, bundle); new_list_entry.sensitive = true; }); } // }}} public void unreveal () { new_list_entry.unreveal (); } } corebird-1.1/src/window/000077500000000000000000000000001260276623600152545ustar00rootroot00000000000000corebird-1.1/src/window/AboutDialog.vala000066400000000000000000000020171260276623600203130ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/about-dialog.ui")] class AboutDialog : Gtk.AboutDialog { [GtkCallback] private void response_cb (int id) { if (id == Gtk.ResponseType.DELETE_EVENT) { this.close (); } else warning ("Unhandled response: %d", id); } } corebird-1.1/src/window/AccountDialog.vala000066400000000000000000000243231260276623600206410ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/account-dialog.ui")] class AccountDialog : Gtk.Dialog { private static const string PAGE_NORMAL = "normal"; private static const string PAGE_DELETE = "delete"; [GtkChild] private Gtk.Entry name_entry; [GtkChild] private AvatarBannerWidget avatar_banner_widget; [GtkChild] private Gtk.Stack delete_stack; [GtkChild] private Gtk.Switch autostart_switch; [GtkChild] private Gtk.Entry website_entry; [GtkChild] private CompletionTextView description_text_view; private unowned Account account; private string old_user_name; private string old_description; private string old_website; private Gdk.Pixbuf? new_avatar = null; private Gdk.Pixbuf? new_banner = null; public AccountDialog (Account account) { GLib.Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0); set_default_response (Gtk.ResponseType.CLOSE); this.account = account; name_entry.text = account.name; avatar_banner_widget.set_account (account); description_text_view.set_account (account); set_transient_data (account.website, account.description); autostart_switch.freeze_notify (); string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); foreach (string acc in startup_accounts) { if (acc == this.account.screen_name) { autostart_switch.active = true; break; } } autostart_switch.thaw_notify (); avatar_banner_widget.avatar_changed.connect ((p) => { new_avatar = p; }); avatar_banner_widget.banner_changed.connect ((b) => { new_banner = b; }); if (account.proxy == null) { account.init_proxy (); account.query_user_info_by_screen_name.begin (null, (obj, res) => { set_transient_data (account.website, account.description); }); } this.set_default_size (350, 450); } private void set_transient_data (string? website, string? description) { website_entry.text = account.website ?? ""; old_user_name = account.name; old_website = account.website ?? ""; old_description = account.description ?? ""; description_text_view.get_buffer ().set_text (account.description ?? ""); } public override void response (int response_id) { if (response_id == Gtk.ResponseType.CLOSE) { save_data (); this.destroy (); } else if (response_id == Gtk.ResponseType.CANCEL) { this.destroy (); } } [GtkCallback] private void delete_button_clicked_cb () { delete_stack.visible_child_name = PAGE_DELETE; } private void save_data () { bool needs_save = (old_user_name != name_entry.text) || (old_description != description_text_view.buffer.text) || (old_website != website_entry.text); bool needs_init = needs_save || (new_avatar != null) || (new_banner != null); if (needs_init && account.proxy == null) { account.init_proxy (); } if (needs_save) { debug ("Saving data..."); var call = account.proxy.new_call (); call.set_function ("1.1/account/update_profile.json"); call.set_method ("POST"); call.add_param ("url", website_entry.text); call.add_param ("name", name_entry.text); call.add_param ("description", description_text_view.buffer.text); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { warning (e.message); Utils.show_error_object (call.get_payload (), "Could not update profile", GLib.Log.LINE, GLib.Log.FILE); } }); /* Update local user data */ account.name = name_entry.text; account.description = description_text_view.buffer.text; account.website = website_entry.text; } if (new_avatar != null) { debug ("Updating avatar..."); uint8[] buffer; try { new_avatar.save_to_buffer (out buffer, "png", null); } catch (GLib.Error e) { warning (e.message); return; } string b64 = GLib.Base64.encode (buffer); var call = account.proxy.new_call (); call.set_function ("1.1/account/update_profile_image.json"); call.set_method ("POST"); call.add_param ("skip_status", "true"); call.add_param ("include_entities", "false"); call.add_param ("image", b64); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), "Could not update your avatar", GLib.Log.LINE, GLib.Log.FILE); return; } /* Locally set new avatar */ var s = Gdk.cairo_surface_create_from_pixbuf (new_avatar, 1, null); account.set_new_avatar (s); }); } if (new_banner != null) { debug ("Updating banner..."); uint8[] buffer; // XXX With large banners, this can be too slow... try { new_banner.save_to_buffer (out buffer, "png", null); } catch (GLib.Error e) { warning (e.message); return; } string b64 = GLib.Base64.encode (buffer); var call = account.proxy.new_call (); call.set_function ("1.1/account/update_profile_banner.json"); call.set_method ("POST"); call.add_param ("banner", b64); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), "Could not update your avatar", GLib.Log.LINE, GLib.Log.FILE); } }); } } [GtkCallback] private void delete_confirm_button_clicked_cb () { /* - Close open window of that account - Remove the account from the db, disk, etc. - Remove the account from the app menu - If this would close the last opened window, set the account of that window to NULL */ var acc_menu = (GLib.Menu) Corebird.account_menu; int64 acc_id = account.id; FileUtils.remove (Dirs.config (@"accounts/$(acc_id).db")); FileUtils.remove (Dirs.config (@"accounts/$(acc_id).png")); FileUtils.remove (Dirs.config (@"accounts/$(acc_id)_small.png")); Corebird.db.exec (@"DELETE FROM `accounts` WHERE `id`='$(acc_id)';"); /* Remove account from startup accounts, if it's in there */ string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); for (int i = 0; i < startup_accounts.length; i++) if (startup_accounts[i] == account.screen_name) { string[] sa_new = new string[startup_accounts.length - 1]; for (int x = 0; x < i; i++) sa_new[x] = startup_accounts[x]; for (int x = i+1; x < startup_accounts.length; x++) sa_new[x] = startup_accounts[x]; Settings.get ().set_strv ("startup-accounts", sa_new); } /* Remove account from account app menu */ for (int i = 0; i < acc_menu.get_n_items (); i++){ Variant item_name = acc_menu.get_item_attribute_value (i, "label", VariantType.STRING); if (item_name.get_string () == "@"+account.screen_name) { acc_menu.remove (i); break; } } Corebird cb = (Corebird) GLib.Application.get_default (); /* Handle windows, i.e. if this MainWindow is the last open one, we want to use it to show the "new account" UI, otherwise we just close it. */ unowned GLib.List windows = cb.get_windows (); Gtk.Window? account_window = null; int n_main_windows = 0; foreach (Gtk.Window win in windows) { if (win is MainWindow) { n_main_windows ++; if (((MainWindow)win).account.id == this.account.id) { account_window = win; } } } debug ("Open main windows: %d", n_main_windows); if (account_window != null) { if (n_main_windows > 1) account_window.destroy (); else ((MainWindow)account_window).change_account (null); } /* Remove the account from the global list of accounts */ Account acc_to_remove = Account.query_account_by_id (account.id); cb.account_removed (acc_to_remove); Account.remove_account (account.screen_name); /* Close this dialog */ this.destroy (); } [GtkCallback] private void delete_cancel_button_clicked_cb () { delete_stack.visible_child_name = PAGE_NORMAL; } [GtkCallback] private void autostart_switch_activate_cb () { bool active = autostart_switch.active; string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); if (active) { foreach (string acc in startup_accounts) { if (acc == this.account.screen_name) { return; } } string[] new_startup_accounts = new string[startup_accounts.length + 1]; int i = 0; foreach (string s in startup_accounts) { new_startup_accounts[i] = s; i ++; } new_startup_accounts[new_startup_accounts.length - 1] = this.account.screen_name; Settings.get ().set_strv ("startup-accounts", new_startup_accounts); } else { string[] new_startup_accounts = new string[startup_accounts.length - 1]; int i = 0; foreach (string acc in startup_accounts) { if (acc != this.account.screen_name) { new_startup_accounts[i] = acc; i ++; } } Settings.get ().set_strv ("startup-accounts", new_startup_accounts); } } } corebird-1.1/src/window/ComposeTweetWindow.vala000066400000000000000000000321211260276623600217260ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/compose-window.ui")] class ComposeTweetWindow : Gtk.ApplicationWindow { public enum Mode { NORMAL, REPLY, QUOTE } [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Box content_box; [GtkChild] private CompletionTextView tweet_text; [GtkChild] private Gtk.Label length_label; [GtkChild] private Gtk.Button send_button; [GtkChild] private Gtk.Button cancel_button; [GtkChild] private Gtk.Spinner title_spinner; [GtkChild] private Gtk.Label title_label; [GtkChild] private Gtk.Stack title_stack; private unowned Account account; private unowned Tweet reply_to; private Mode mode; private Gee.ArrayList image_buttons; public ComposeTweetWindow (Gtk.Window? parent, Account acc, Tweet? reply_to = null, Mode mode = Mode.NORMAL) { this.set_show_menubar (false); this.account = acc; this.reply_to = reply_to; this.mode = mode; this.tweet_text.set_account (acc); this.application = (Gtk.Application)GLib.Application.get_default (); image_buttons = new Gee.ArrayList (); avatar_image.surface = acc.avatar; if (mode != Mode.QUOTE) length_label.label = Tweet.MAX_LENGTH.to_string (); else length_label.label = (Tweet.MAX_LENGTH - Twitter.short_url_length_https).to_string (); tweet_text.buffer.changed.connect (buffer_changed_cb); if (parent != null) { this.set_transient_for (parent); } if (mode != Mode.NORMAL) { var list = new Gtk.ListBox (); list.selection_mode = Gtk.SelectionMode.NONE; TweetListEntry reply_entry = new TweetListEntry (reply_to, (MainWindow)parent, acc); reply_entry.activatable = false; reply_entry.read_only = true; reply_entry.show (); list.add (reply_entry); list.show (); content_box.pack_start (list, false, true); content_box.reorder_child (list, 0); } if (mode == Mode.REPLY) { StringBuilder mention_builder = new StringBuilder (); if (reply_to.screen_name != account.screen_name) { mention_builder.append ("@").append (reply_to.screen_name); } if (reply_to.retweeted_tweet != null) { if (mention_builder.len > 0) mention_builder.append (" "); mention_builder.append ("@").append (reply_to.source_tweet.author.screen_name); } foreach (string s in reply_to.get_mentions ()) { if (s == "@" + account.screen_name) continue; if (mention_builder.len > 0) mention_builder.append (" "); mention_builder.append (s); } /* Only add a space if we actually added some screen names */ if (mention_builder.len > 0) mention_builder.append (" "); tweet_text.buffer.text = mention_builder.str; } else if (mode == Mode.QUOTE) { assert (reply_to != null); this.title_label.label = _("Quote tweet"); } //Let the text view immediately grab the keyboard focus tweet_text.grab_focus (); Gtk.AccelGroup ag = new Gtk.AccelGroup (); ag.connect (Gdk.Key.Escape, 0, Gtk.AccelFlags.LOCKED, escape_pressed_cb); ag.connect (Gdk.Key.Return, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.LOCKED, () => {start_send_tweet (); return true;}); this.add_accel_group (ag); /* Add AddImageButton because we can't do it in the ui definition for some reason */ if (mode != Mode.QUOTE) add_image_button (true); } private void buffer_changed_cb () { recalc_tweet_length (); } private void recalc_tweet_length () { Gtk.TextIter start, end; tweet_text.buffer.get_bounds (out start, out end); string text = tweet_text.buffer.get_text (start, end, true); int media_count = 0; if (get_effective_media_count () > 0) media_count = 1; int length = TweetUtils.calc_tweet_length (text, media_count); if (this.mode == Mode.QUOTE) length += Twitter.short_url_length_https; length_label.label = (Tweet.MAX_LENGTH - length).to_string (); if (length > 0 && length <= Tweet.MAX_LENGTH) send_button.sensitive = true; else send_button.sensitive = false; } [GtkCallback] private void start_send_tweet () { if (!send_button.sensitive) return; int media_count = get_effective_media_count (); Collect collect_obj = new Collect (media_count); int64[] media_ids = new int64[media_count]; title_stack.visible_child = title_spinner; title_spinner.start (); cancel_button.sensitive = false; send_button.sensitive = false; tweet_text.sensitive = false; /* Remove unused media button */ foreach (AddImageButton btn in image_buttons) if (btn.image == null) { btn.sensitive = false; break; } if (media_count > 0) { /* Set up a new proxy because why not */ Rest.OAuthProxy proxy = new Rest.OAuthProxy (Settings.get_consumer_key (), Settings.get_consumer_secret (), "https://upload.twitter.com/", false); proxy.token = account.proxy.token; proxy.token_secret = account.proxy.token_secret; int i = 0; foreach (AddImageButton aib in image_buttons) { if (aib.image != null) { int k = i; aib.start_progress (); upload_media.begin (aib.image_path, proxy, (obj, res) => { int64 id; try { id = upload_media.end (res); } catch (GLib.Error e) { warning (e.message); collect_obj.emit (e); aib.set_error (e.message); return; } aib.set_success (); media_ids[k] = id; collect_obj.emit (); }); i ++; } } collect_obj.finished.connect ((error) => { title_stack.visible_child = title_label; cancel_button.sensitive = true; send_button.sensitive = true; tweet_text.sensitive = true; send_tweet (error, media_ids); }); } else { /* No media attached so just send the text */ send_tweet (null, media_ids); } } private void send_tweet (GLib.Error? error, int64[] ids) { if (error != null) { GLib.error (error.message); } Gtk.TextIter start, end; tweet_text.buffer.get_start_iter (out start); tweet_text.buffer.get_end_iter (out end); string text = tweet_text.buffer.get_text (start, end, true); var call = account.proxy.new_call (); call.set_method ("POST"); if (this.reply_to != null && mode == Mode.REPLY) { call.add_param("in_reply_to_status_id", reply_to.id.to_string ()); } else if (this.reply_to != null && mode == Mode.QUOTE) { MiniTweet mt = reply_to.retweeted_tweet ?? reply_to.source_tweet; text += " https://twitter.com/%s/status/%s".printf (mt.author.screen_name, mt.id.to_string ()); } call.add_param ("status", text); if (ids.length > 0) { StringBuilder id_str = new StringBuilder (); id_str.append (ids[0].to_string ()); for (int i = 1; i < ids.length; i ++) { id_str.append (",").append (ids[i].to_string ()); } call.add_param ("media_ids", id_str.str); } call.set_function ("1.1/statuses/update.json"); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { critical (e.message); Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } finally { this.destroy (); } }); this.hide (); } private async int64 upload_media (string path, Rest.Proxy proxy) throws GLib.Error { var call = proxy.new_call (); call.set_function ("1.1/media/upload.json"); call.set_method ("POST"); uint8[] file_contents; GLib.File media_file = GLib.File.new_for_path (path); media_file.load_contents (null, out file_contents, null); Rest.Param param = new Rest.Param.full ("media", Rest.MemoryUse.COPY, file_contents, "multipart/form-data", path); call.add_param_full (param); yield call.invoke_async (null); var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { warning (e.message); //XXX Error handling return -1; } var root = parser.get_root ().get_object (); return root.get_int_member ("media_id"); } [GtkCallback] private void cancel_clicked (Gtk.Widget source) { destroy (); } private bool escape_pressed_cb () { this.destroy (); return true; } public void set_text (string text) { tweet_text.buffer.text = text; } /* Image handling stuff {{{ */ private void add_image_button (bool initially_visible = false) { if (image_buttons.size >= Twitter.max_media_per_upload) return; var image_button = new AddImageButton (); var revealer = new Gtk.Revealer (); image_button.remove_clicked.connect (remove_image_clicked_cb); image_button.add_clicked.connect (add_image_clicked_cb); image_button.notify["image"].connect (() => { if (image_button.image != null) { add_image_button (); recalc_tweet_length (); } }); revealer.add (image_button); revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; revealer.reveal_child = initially_visible; revealer.show_all (); content_box.pack_start (revealer, false, false); if (!initially_visible) revealer.reveal_child = true; image_buttons.add (image_button); } private void add_image_clicked_cb (AddImageButton source) { var fcd = new Gtk.FileChooserDialog(_("Select Image"), this, Gtk.FileChooserAction.OPEN, _("Cancel"), Gtk.ResponseType.CANCEL, _("Choose"), Gtk.ResponseType.ACCEPT); fcd.set_modal (true); var filter = new Gtk.FileFilter (); filter.add_mime_type ("image/png"); filter.add_mime_type ("image/jpeg"); filter.add_mime_type ("image/gif"); fcd.set_filter (filter); var preview_widget = new Gtk.Image (); fcd.set_preview_widget (preview_widget); fcd.update_preview.connect (() => { string? uri = fcd.get_preview_uri (); if (uri != null && uri.has_prefix ("file://")) { try { int final_size = 130; var p = new Gdk.Pixbuf.from_file (GLib.File.new_for_uri (uri).get_path ()); int w = p.get_width (); int h = p.get_height (); if (w > h) { double ratio = final_size / (double) w; w = final_size; h = (int)(h * ratio); } else { double ratio = final_size / (double) h; w = (int)(w * ratio); h = final_size; } var scaled = p.scale_simple (w, h, Gdk.InterpType.BILINEAR); preview_widget.set_from_pixbuf (scaled); preview_widget.show (); } catch (GLib.Error e) { preview_widget.hide (); } } else preview_widget.hide (); }); if (fcd.run () == Gtk.ResponseType.ACCEPT) { string file = fcd.get_filename (); try { var pixbuf = new Gdk.Pixbuf.from_file (file); var thumb = Utils.slice_pixbuf (pixbuf, 500, MultiMediaWidget.HEIGHT); source.image = thumb; source.image_path = file; } catch (GLib.Error e) { warning (e.message); } } fcd.close (); } private void remove_image_clicked_cb (AddImageButton source) { source.image = null; Gtk.Revealer revealer = (Gtk.Revealer)source.parent; revealer.reveal_child = false; revealer.notify["child-revealed"].connect (() => { content_box.remove (revealer); image_buttons.remove (source); }); recalc_tweet_length (); } private int get_effective_media_count () { int c = 0; foreach (AddImageButton btn in image_buttons) if (btn.image != null) c ++; return c; } /* }}} */ } corebird-1.1/src/window/ImageCropDialog.vala000066400000000000000000000077041260276623600211170ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/image-crop-dialog.ui")] public class ImageCropDialog : Gtk.Dialog { [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.FileChooserWidget file_chooser; [GtkChild] private CropWidget crop_widget; [GtkChild] private Gtk.Button back_button; [GtkChild] private Gtk.Button next_button; [GtkChild] private Gtk.Label error_label; public signal void image_cropped (Gdk.Pixbuf result); public int min_width; public int min_height; public ImageCropDialog (double aspect_ratio) { GLib.Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0); Gtk.FileFilter filter = new Gtk.FileFilter (); filter.add_mime_type ("image/png"); filter.add_mime_type ("image/jpeg"); file_chooser.set_filter (filter); crop_widget.desired_aspect_ratio = aspect_ratio; } public override void response (int response_id) { if (response_id == Gtk.ResponseType.CANCEL) { this.destroy (); } else if (response_id == Gtk.ResponseType.OK) { next.begin (); } else if (response_id == 1) { // back stack.visible_child = file_chooser; back_button.sensitive = false; next_button.label = _("Next"); selection_changed_cb (); } } [GtkCallback] private void selection_changed_cb () { string? selected_file = file_chooser.get_filename (); if (selected_file == null) return; GLib.File f = GLib.File.new_for_path (selected_file); GLib.FileType file_type = f.query_file_type (GLib.FileQueryInfoFlags.NONE, null); if (file_type == GLib.FileType.DIRECTORY) next_button.sensitive = false; else next_button.sensitive = true; } [GtkCallback] private async void next () { if (stack.visible_child == file_chooser) { /* Prepare crop widget with selected image */ string selected_file = file_chooser.get_filename (); stack.visible_child = crop_widget; /* Load the file now, check for min size etc. */ Gdk.Pixbuf? image = null; try { image = new Gdk.Pixbuf.from_file (selected_file); } catch (GLib.Error e) { warning (e.message); return; } if (image.get_width () >= min_width && image.get_height () >= min_height) { crop_widget.set_image (image); next_button.label = _("Save"); next_button.sensitive = true; back_button.sensitive = true; } else { string error_str = ""; error_str += _("Image does not meet minimum size requirements:") + "\n"; error_str += ngettext ("Minimum width: %d pixel", "Minimum width: %d pixels", min_width) .printf (min_width) + "\n"; error_str += ngettext ("Minimum height: %d pixel", "Minimum height: %d pixels", min_height) .printf (min_height); error_label.label = error_str; stack.visible_child = error_label; back_button.sensitive = true; next_button.sensitive = false; } } else { /* Crop the widget and save it... */ image_cropped (crop_widget.get_cropped_image ()); this.destroy (); } } public void set_min_size (int min_width) { crop_widget.set_min_size (min_width); } } corebird-1.1/src/window/MediaDialog.vala000066400000000000000000000102111260276623600202530ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/media-dialog.ui")] class MediaDialog : Gtk.Window { [GtkChild] private Gtk.Overlay overlay; //[GtkChild] //private Gtk.Button next_button; //[GtkChild] //private Gtk.Button back_button; //[GtkChild] //private Gtk.Revealer back_revealer; //[GtkChild] //private Gtk.Revealer next_revealer; private unowned Tweet tweet; private int cur_index = 0; public MediaDialog (Tweet tweet, int start_media_index) { Media cur_media = tweet.medias[start_media_index]; this.tweet = tweet; this.cur_index = start_media_index; change_media (cur_media); } private void change_media (Media media) { /* Remove the current child */ var cur_child = overlay.get_child (); int cur_width = 0, cur_height = 0, new_width, new_height; if (overlay.get_child () != null) { overlay.remove (cur_child); cur_child.get_size_request (out cur_width, out cur_height); } Gtk.Widget new_widget = null; if (media.type == MediaType.IMAGE || media.type == MediaType.GIF) { new_widget = new MediaImageWidget (media.path); } else if (media.type == MediaType.VINE || media.type == MediaType.ANIMATED_GIF || media.type == MediaType.TWITTER_VIDEO) { new_widget = new MediaVideoWidget (media); } else { critical ("Unknown media type %d", media.type); return; } overlay.add (new_widget); new_widget.show_all (); new_widget.get_size_request (out new_width, out new_height); if ((new_width != cur_width || new_height != cur_height) && new_width > 0 && new_height > 0) { this.resize (new_width, new_height); } this.queue_resize (); this.queue_draw (); //if (cur_index >= tweet.medias.length - 1) //next_button.hide (); //else //next_button.show (); //if (cur_index <= 0) //back_button.hide (); //else //back_button.show (); } private void next_media () { if (cur_index < tweet.medias.length - 1) { cur_index ++; change_media (tweet.medias[cur_index]); } } private void previous_media () { if (cur_index > 0) { cur_index --; change_media (tweet.medias[cur_index]); } } //[GtkCallback] //private void next_button_clicked_cb () { //next_media (); //} //[GtkCallback] //private void back_button_clicked_cb () { //previous_media (); //} [GtkCallback] private bool key_press_event_cb (Gdk.EventKey evt) { if (evt.keyval == Gdk.Key.Left) previous_media (); else if (evt.keyval == Gdk.Key.Right) next_media (); else this.destroy (); return true; } [GtkCallback] private bool button_press_event_cb () { this.destroy (); return true; } [GtkCallback] private bool leave_notify_cb () { //back_revealer.reveal_child= false; //next_revealer.reveal_child= false; return true; } [GtkCallback] private bool enter_notify_cb () { //back_revealer.reveal_child= true; //next_revealer.reveal_child= true; return true; } /* Fake handlers to route events from the overlay box down to the actual child of the GtkOverlay */ //[GtkCallback] //private bool fake_button_press_cb (Gdk.EventButton e) { //return overlay.get_child ().event (e); //} //[GtkCallback] //private bool fake_scroll_event_cb (Gdk.EventScroll e) { //return overlay.get_child ().event (e); //} } corebird-1.1/src/window/ModifyFilterDialog.vala000066400000000000000000000071341260276623600216430ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/modify-filter-dialog.ui")] class ModifyFilterDialog : Gtk.Dialog { [GtkChild] private Gtk.Entry regex_entry; [GtkChild] private Gtk.Label regex_status_label; [GtkChild] private Gtk.TextView regex_test_text; [GtkChild] private Gtk.Button save_button; private GLib.Regex regex; private unowned Account account; private unowned Filter filter; private unowned MainWindow main_window; /** created will be true if the filter has just been created by the user(i.e. not modified) */ public signal void filter_added (Filter filter, bool created); public ModifyFilterDialog (MainWindow parent, Account account, Filter? filter = null) { GLib.Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0); this.set_transient_for (parent); this.application = parent.get_application (); this.account = account; if (filter != null) { regex_entry.text = filter.content; this.title = _("Modify Filter"); } this.filter = filter; this.main_window = parent; } construct { regex_test_text.buffer.changed.connect (regex_entry_changed_cb); } public override void response (int response_id) { if (response_id == Gtk.ResponseType.CANCEL) { this.destroy (); } else if (response_id == Gtk.ResponseType.OK) { save_filter (); this.destroy (); } } [GtkCallback] private void regex_entry_changed_cb () { try { regex = new GLib.Regex (regex_entry.text); } catch (GLib.RegexError e) { regex_status_label.label = e.message; save_button.sensitive = false; return; } bool matches = regex.match (regex_test_text.buffer.text); if (matches) { regex_status_label.label = _("Matches"); } else { regex_status_label.label = _("Doesn't match"); } save_button.sensitive = (regex_entry.text.length != 0); } private void save_filter () { string content = regex_entry.text; if (this.filter == null) { Filter f = Utils.create_persistent_filter (content, account); //int id = (int)account.db.insert ("filters") //.val ("content", content) //.run(); //Filter f = new Filter (content); //f.id = id; //account.add_filter (f); filter_added (f, true); } else { /* We update the existing filter */ account.db.update ("filters").val ("content", content) .where_eq ("id", filter.id.to_string ()) .run (); foreach (var f in account.filters) { if (f.id == this.filter.id) { f.reset (content); filter_added (f, false); break; } } } /* Update timelines */ main_window.rerun_filters (); } } corebird-1.1/src/window/ModifySnippetDialog.vala000066400000000000000000000074431260276623600220430ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/modify-snippet-dialog.ui")] class ModifySnippetDialog : Gtk.Dialog { [GtkChild] private Gtk.Entry key_entry; [GtkChild] private Gtk.Entry value_entry; [GtkChild] private Gtk.Label error_label; [GtkChild] private Gtk.Button save_button; [GtkChild] private Gtk.Button delete_button; private string? old_key = null; public signal void snippet_updated (string? old_key, string? key, string? value); public ModifySnippetDialog (string? key = null, string? value = null) { GLib.Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0); if (key != null) { assert (value != null); this.old_key = key; this.key_entry.text = key; this.value_entry.text = value; this.delete_button.show (); this.title = _("Modify Snippet"); } key_entry.buffer.inserted_text.connect (validate_input); key_entry.buffer.deleted_text.connect (validate_input); value_entry.buffer.inserted_text.connect (validate_input); value_entry.buffer.deleted_text.connect (validate_input); } private void validate_input () { string key = key_entry.text.strip (); string value = value_entry.text.strip (); key_entry.get_style_context ().remove_class ("error"); value_entry.get_style_context ().remove_class ("error"); error_label.label = ""; save_button.sensitive = true; if (key == "") { error_label.label = _("Snippet can't be empty"); key_entry.get_style_context ().add_class ("error"); save_button.sensitive = false; return; } if (value == "") { error_label.label = _("Replacement can't be empty"); value_entry.get_style_context ().add_class ("error"); save_button.sensitive = false; return; } if (key.contains (" ") || key.contains ("\t")) { error_label.label = _("Snippet may not contain whitespace"); key_entry.get_style_context ().add_class ("error"); save_button.sensitive = false; return; } if (Corebird.snippet_manager.get_snippet (key) != null && this.old_key != key) { error_label.label = _("Snippet already exists"); save_button.sensitive = false; return; } } private void save_snippet () { string new_value = this.value_entry.text; string new_key = this.key_entry.text; if (this.old_key != null) { Corebird.snippet_manager.set_snippet (old_key, new_key, new_value); } else { Corebird.snippet_manager.insert_snippet (new_key, new_value); } this.snippet_updated (old_key, new_key, new_value); } [GtkCallback] private void delete_button_clicked_cb () { assert (this.old_key != null); Corebird.snippet_manager.remove_snippet (this.old_key); this.snippet_updated (this.old_key, null, null); this.destroy (); } public override void response (int response_id) { if (response_id == Gtk.ResponseType.CANCEL) { this.destroy (); } else if (response_id == Gtk.ResponseType.OK) { save_snippet (); this.destroy (); } } } corebird-1.1/src/window/SettingsDialog.vala000066400000000000000000000222211260276623600210400ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/settings-dialog.ui")] class SettingsDialog : Gtk.Window { [GtkChild] private Gtk.Switch on_new_mentions_switch; [GtkChild] private Gtk.Switch round_avatar_switch; [GtkChild] private Gtk.Switch on_new_dms_switch; [GtkChild] private Gtk.ComboBoxText on_new_tweets_combobox; [GtkChild] private Gtk.Switch auto_scroll_on_new_tweets_switch; [GtkChild] private Gtk.SpinButton max_media_size_spin_button; [GtkChild] private Gtk.Stack main_stack; [GtkChild] private Gtk.Switch double_click_activation_switch; [GtkChild] private Gtk.ListBox sample_tweet_list; [GtkChild] private Gtk.Switch remove_trailing_hashtags_switch; [GtkChild] private Gtk.Switch remove_media_links_switch; [GtkChild] private Gtk.ListBox snippet_list_box; private TweetListEntry sample_tweet_entry; public SettingsDialog (Corebird application) { this.application = application; this.type_hint = Gdk.WindowTypeHint.DIALOG; // Notifications Page Settings.get ().bind ("round-avatars", round_avatar_switch, "active", SettingsBindFlags.DEFAULT); Settings.get ().bind ("new-tweets-notify", on_new_tweets_combobox, "active-id", SettingsBindFlags.DEFAULT); Settings.get ().bind ("new-mentions-notify", on_new_mentions_switch, "active", SettingsBindFlags.DEFAULT); Settings.get ().bind ("new-dms-notify", on_new_dms_switch, "active", SettingsBindFlags.DEFAULT); // Interface page auto_scroll_on_new_tweets_switch.notify["active"].connect (() => { on_new_tweets_combobox.sensitive = !auto_scroll_on_new_tweets_switch.active; }); Settings.get ().bind ("auto-scroll-on-new-tweets", auto_scroll_on_new_tweets_switch, "active", SettingsBindFlags.DEFAULT); Settings.get ().bind ("max-media-size", max_media_size_spin_button, "value", SettingsBindFlags.DEFAULT); Settings.get ().bind ("double-click-activation", double_click_activation_switch, "active", SettingsBindFlags.DEFAULT); // Set up sample tweet {{{ var sample_tweet = new Tweet (); sample_tweet.source_tweet = new MiniTweet(); sample_tweet.source_tweet.author = UserIdentity() { id = 12, screen_name = "corebirdclient", user_name = "Corebird" }; string sample_text = _("Hey, check out this new #Corebird version! \\ (•◡•) / #cool #newisalwaysbetter"); Gdk.Pixbuf? a = null; try { a = Gtk.IconTheme.get_default ().load_icon ("corebird", 48, Gtk.IconLookupFlags.FORCE_SIZE); sample_tweet.avatar = Gdk.cairo_surface_create_from_pixbuf (a, 1, null); } catch (GLib.Error e) { warning (e.message); } sample_tweet.source_tweet.text = sample_text; try { var regex = new GLib.Regex ("#\\w+"); GLib.MatchInfo match_info; bool matched = regex.match (sample_text, 0, out match_info); assert (matched); sample_tweet.source_tweet.entities = new TextEntity[3]; int i = 0; while (match_info.matches ()) { assert (match_info.get_match_count () == 1); int from, to; match_info.fetch_pos (0, out from, out to); string match = match_info.fetch (0); sample_tweet.source_tweet.entities[i] = TextEntity () { from = sample_text.char_count (from), to = sample_text.char_count (to), display_text = match, target = "foobar" }; match_info.next (); i ++; } } catch (GLib.RegexError e) { critical (e.message); } // Just to be sure TweetUtils.sort_entities (ref sample_tweet.source_tweet.entities); this.sample_tweet_entry = new TweetListEntry (sample_tweet, null, new Account (10, "", "")); sample_tweet_entry.activatable = false; sample_tweet_entry.read_only = true; sample_tweet_entry.show (); this.sample_tweet_list.add (sample_tweet_entry); // }}} var text_transform_flags = Settings.get_text_transform_flags (); remove_trailing_hashtags_switch.active = (TransformFlags.REMOVE_TRAILING_HASHTAGS in text_transform_flags); remove_media_links_switch.active = (TransformFlags.REMOVE_MEDIA_LINKS in text_transform_flags); // Fill snippet list box Corebird.snippet_manager.query_snippets ((key, value) => { var e = new SnippetListEntry (key, value); e.show_all (); snippet_list_box.add (e); }); add_accels (); load_geometry (); } [GtkCallback] private bool window_destroy_cb () { save_geometry (); return false; } [GtkCallback] private void snippet_entry_activated_cb (Gtk.ListBoxRow row) { var snippet_row = (SnippetListEntry) row; var d = new ModifySnippetDialog (snippet_row.key, snippet_row.value); d.snippet_updated.connect (snippet_updated_func); d.set_transient_for (this); d.modal = true; d.show (); } [GtkCallback] private void add_snippet_button_clicked_cb () { var d = new ModifySnippetDialog (); d.snippet_updated.connect (snippet_updated_func); d.set_transient_for (this); d.modal = true; d.show (); } private void snippet_updated_func (string? old_key, string? key, string? value) { if (old_key != null && key == null && value == null) { foreach (var _row in snippet_list_box.get_children ()) { var srow = (SnippetListEntry) _row; if (srow.key == old_key) { srow.reveal (); break; } } return; } if (old_key == null) { var e = new SnippetListEntry (key, value); e.show_all (); snippet_list_box.add (e); } else { foreach (var _row in snippet_list_box.get_children ()) { var srow = (SnippetListEntry) _row; if (srow.key == old_key) { srow.key = key; srow.value = value; break; } } } } private void load_geometry () { GLib.Variant geom = Settings.get ().get_value ("settings-geometry"); int x = 0, y = 0, w = 0, h = 0; x = geom.get_child_value (0).get_int32 (); y = geom.get_child_value (1).get_int32 (); w = geom.get_child_value (2).get_int32 (); h = geom.get_child_value (3).get_int32 (); if (w == 0 || h == 0) return; move (x, y); resize (w, h); } private void save_geometry () { var builder = new GLib.VariantBuilder (GLib.VariantType.TUPLE); int x = 0, y = 0, w = 0, h = 0; get_position (out x, out y); w = get_allocated_width (); h = get_allocated_height (); builder.add_value (new GLib.Variant.int32(x)); builder.add_value (new GLib.Variant.int32(y)); builder.add_value (new GLib.Variant.int32(w)); builder.add_value (new GLib.Variant.int32(h)); Settings.get ().set_value ("settings-geometry", builder.end ()); } private void add_accels () { Gtk.AccelGroup ag = new Gtk.AccelGroup(); ag.connect (Gdk.Key.Escape, 0, Gtk.AccelFlags.LOCKED, () => {this.destroy (); return true;}); ag.connect (Gdk.Key.@1, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_stack.visible_child_name = "interface"; return true;}); ag.connect (Gdk.Key.@2, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_stack.visible_child_name = "notifications"; return true;}); ag.connect (Gdk.Key.@3, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_stack.visible_child_name = "tweet"; return true;}); ag.connect (Gdk.Key.@4, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_stack.visible_child_name = "snippets"; return true;}); this.add_accel_group(ag); } [GtkCallback] private void remove_trailing_hashtags_cb () { if (remove_trailing_hashtags_switch.active) { Settings.add_text_transform_flag (TransformFlags.REMOVE_TRAILING_HASHTAGS); } else { Settings.remove_text_transform_flag (TransformFlags.REMOVE_TRAILING_HASHTAGS); } } [GtkCallback] private void remove_media_links_cb () { if (remove_media_links_switch.active) { Settings.add_text_transform_flag (TransformFlags.REMOVE_MEDIA_LINKS); } else { Settings.remove_text_transform_flag (TransformFlags.REMOVE_MEDIA_LINKS); } } } corebird-1.1/src/window/UserListDialog.vala000066400000000000000000000160541260276623600210210ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ struct TwitterList { int64 id; string name; string description; string mode; uint n_members; } class UserListDialog : Gtk.Dialog { private unowned Account account; private unowned MainWindow main_window; private Gtk.ListBox list_list_box = new Gtk.ListBox (); private Gtk.Label placeholder_label = new Gtk.Label (""); private int64 user_id; public UserListDialog (MainWindow parent, Account account, int64 user_id) { GLib.Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0); this.title = _("Add to or Remove User From List"); this.main_window = parent; this.user_id = user_id; this.account = account; set_modal (true); set_transient_for (parent); set_default_size (250, 200); add_button (_("Cancel"), Gtk.ResponseType.CANCEL); add_button (_("Save"), Gtk.ResponseType.OK); set_default_response (Gtk.ResponseType.OK); var content_box = get_content_area (); content_box.border_width = 0; var scroller = new Gtk.ScrolledWindow (null, null); list_list_box.selection_mode = Gtk.SelectionMode.NONE; list_list_box.row_activated.connect ((row) => { if (!(row is ListUserEntry)) { warning ("Row != ListUserEntry!"); return; } ((ListUserEntry)row).toggle (); }); scroller.add (list_list_box); content_box.pack_start (scroller, true, true); placeholder_label.label = _("You have no lists."); placeholder_label.get_style_context ().add_class ("dim-label"); placeholder_label.show (); list_list_box.set_placeholder (placeholder_label); } public void load_lists () { var lists_page = (ListsPage)main_window.get_page (Page.LISTS); lists_page.get_user_lists.begin ((obj, res) => { TwitterList[] lists = lists_page.get_user_lists.end (res); foreach (var list in lists) { var l = new ListUserEntry (list.name, list.description); l.id = list.id; if (list.n_members >= 500) l.disable (); list_list_box.add (l); } this.show_all (); }); var call = account.proxy.new_call (); call.set_function ("1.1/lists/memberships.json"); call.add_param ("user_id", user_id.to_string ()); call.add_param ("filter_to_owned_lists", "true"); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical (e.message); return; } var root = parser.get_root ().get_object (); var list_arr = root.get_array_member ("lists"); list_arr.foreach_element ((arr, index, node) => { int64 id = node.get_object ().get_int_member ("id"); list_list_box.@foreach ((w) => { var lue = (ListUserEntry) w; if (lue.id == id) { lue.check (); lue.enable (); } }); }); }); } public override void response (int response_id) { if (response_id == Gtk.ResponseType.CANCEL) { this.destroy (); } else if (response_id == Gtk.ResponseType.OK) { var list_entries = list_list_box.get_children (); foreach (Gtk.Widget w in list_entries) { var lue = (ListUserEntry) w; if (lue.changed) { debug ("VALUE CHANGED"); if (lue.active) { // Add user to the list add_user (lue.id); } else { // Remove user from the list remove_user (lue.id); } } } this.destroy (); } } private void add_user (int64 list_id) { var call = account.proxy.new_call (); call.set_function ("1.1/lists/members/create.json"); call.set_method ("POST"); call.add_param ("list_id", list_id.to_string ()); call.add_param ("user_id", user_id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } }); } private void remove_user (int64 list_id) { var call = account.proxy.new_call (); call.set_function ("1.1/lists/members/destroy.json"); call.set_method ("POST"); call.add_param ("list_id", list_id.to_string ()); call.add_param ("user_id", user_id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } }); } } class ListUserEntry : Gtk.ListBoxRow { public int64 id; public new bool changed = false; private Gtk.CheckButton added_checkbox = new Gtk.CheckButton (); public bool active { get { return added_checkbox.active; } } public ListUserEntry (string list_name, string description) { var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); box.margin = 6; added_checkbox.valign = Gtk.Align.CENTER; added_checkbox.margin_start = 6; box.pack_start (added_checkbox, false, false); var box2 = new Gtk.Box (Gtk.Orientation.VERTICAL, 3); var label = new Gtk.Label ("" + list_name + ""); label.use_markup = true; label.halign = Gtk.Align.START; box2.pack_start (label, true, false); var desc_label = new Gtk.Label (description); desc_label.get_style_context ().add_class ("dim-label"); desc_label.halign = Gtk.Align.START; desc_label.ellipsize = Pango.EllipsizeMode.END; box2.pack_start (desc_label, true, false); box.pack_start (box2, true, true); add (box); added_checkbox.toggled.connect (() => { changed = !changed; }); } public void check () { added_checkbox.active = true; changed = false; } public void toggle () { added_checkbox.active = !added_checkbox.active; } public void disable () { this.added_checkbox.sensitive = false; } public void enable () { this.added_checkbox.sensitive = true; } } corebird-1.1/tests/000077500000000000000000000000001260276623600143205ustar00rootroot00000000000000corebird-1.1/tests/.gitignore000066400000000000000000000003031260276623600163040ustar00rootroot00000000000000*.log *.trs *.stamp-t _test.db tweet_length media utils bundlehistory usercounter hometimeline tweet_entities filters sql tweet_parsing multimedia highlighting friends tweetmodel texttransform corebird-1.1/tests/Makefile.am000066400000000000000000000053041260276623600163560ustar00rootroot00000000000000AM_CPPFLAGS = $(CB_CFLAGS) -I$(top_srcdir)/src TESTS = \ tweetmodel \ tweet_length \ utils \ bundlehistory \ usercounter \ media \ tweet_parsing \ filters \ sql \ highlighting \ friends \ texttransform check_PROGRAMS = $(TESTS) # Always add -g to the test cases (for easier debugging) CB_VALA_FLAGS="$CB_VALA_FLAGS -g" tweet_length_SOURCES = tweet_length.vala tweet_length_LDADD = $(top_builddir)/src/libcorebird.la tweet_length_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ media_SOURCES = inlinemediadownloader.vala media_LDADD = $(top_builddir)/src/libcorebird.la media_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ utils_SOURCES = utils.vala utils_LDADD = $(top_builddir)/src/libcorebird.la utils_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ bundlehistory_SOURCES = bundlehistory.vala bundlehistory_LDADD = $(top_builddir)/src/libcorebird.la bundlehistory_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ usercounter_SOURCES = usercounter.vala usercounter_LDADD = $(top_builddir)/src/libcorebird.la usercounter_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ filters_SOURCES = filters.vala resources.c filters_LDADD = $(top_builddir)/src/libcorebird.la filters_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ sql_SOURCES = sql.vala sql_LDADD = $(top_builddir)/src/libcorebird.la sql_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ tweet_parsing_SOURCES = tweet_parsing.vala resources.c tweet_parsing_LDADD = $(top_builddir)/src/libcorebird.la tweet_parsing_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ highlighting_SOURCES = highlighting.vala highlighting_LDADD = $(top_builddir)/src/libcorebird.la highlighting_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ friends_SOURCES = friends.vala friends_LDADD = $(top_builddir)/src/libcorebird.la friends_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ tweetmodel_SOURCES = tweetmodel.vala tweetmodel_LDADD = $(top_builddir)/src/libcorebird.la tweetmodel_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ texttransform_SOURCES = texttransform.vala texttransform_LDADD = $(top_builddir)/src/libcorebird.la texttransform_VALAFLAGS = $(top_builddir)/src/corebird.vapi @CB_VALA_FLAGS@ GRESDEPS = $(top_srcdir)/$1 $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir=$(top_srcdir) $(top_srcdir)/$1) resource_deps = $(call GRESDEPS,resources.xml) resources.c: $(resource_deps) $(GLIB_COMPILE_RESOURCES) $(top_srcdir)/resources.xml --target=resources.c --generate-source --sourcedir=$(top_srcdir) CLEANFILES = *.c corebird-1.1/tests/__sql_init1.sql000066400000000000000000000000311260276623600172340ustar00rootroot00000000000000PRAGMA user_version = 1; corebird-1.1/tests/__sql_init2.sql000066400000000000000000000000311260276623600172350ustar00rootroot00000000000000PRAGMA user_version = 2; corebird-1.1/tests/_sql_init1.sql000066400000000000000000000000311260276623600170750ustar00rootroot00000000000000PRAGMA user_version = 1; corebird-1.1/tests/bundlehistory.vala000066400000000000000000000026111260276623600200600ustar00rootroot00000000000000 void all () { var history = new BundleHistory (5); history.push (1, null); history.push (2, null); history.push (3, null); history.push (4, null); history.push (5, null); assert (history.current == 5); history.back (); assert (history.current == 4); history.back (); assert (history.current == 3); history.forward (); assert (history.current == 4); history.push (10, null); assert (history.current == 10); history.forward (); assert (history.current == 10); history.forward (); assert (history.current == 10); } void end () { var history = new BundleHistory (5); assert (history.at_end ()); history.push (1, null); assert (history.at_end ()); history.push (2, null); assert (history.at_end ()); history.back (); assert (!history.at_end ()); } void equals () { var bundle1 = new Bundle (); bundle1.put_string ("a", "1"); bundle1.put_string ("b", "3"); var bundle2 = new Bundle (); bundle2.put_string ("b", "3"); bundle2.put_string ("a", "1"); assert (bundle1.equals (bundle2)); assert (!bundle1.equals (null)); var bundle3 = new Bundle (); assert (!bundle3.equals (bundle1)); } int main (string[] args) { GLib.Test.init (ref args); GLib.Test.add_func ("/bundlehistory/all", all); GLib.Test.add_func ("/bundlehistory/end", end); GLib.Test.add_func ("/bundlehistory/equals", equals); return GLib.Test.run (); } corebird-1.1/tests/filters.vala000066400000000000000000000230271260276623600166410ustar00rootroot00000000000000 // {{{ const string TD1 = """ { "created_at" : "Mon May 05 06:48:32 +0000 2014", "id" : 463208606784311296, "id_str" : "463208606784311296", "text" : "RT @BlackForestTeam: DIESELSTÖRMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e", "source" : "web", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 62574927, "id_str" : "62574927", "name" : "Frozenbyte", "screen_name" : "Frozenbyte", "location" : "Helsinki, Finland", "description" : "We're an independent game developer. Follow us on Twitter to get the latest news on our games! For support issues please get in touch via email.", "url" : "http://t.co/NlgW9k9ZXj", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/NlgW9k9ZXj", "expanded_url" : "http://www.frozenbyte.com", "display_url" : "frozenbyte.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 5682, "friends_count" : 137, "listed_count" : 242, "created_at" : "Mon Aug 03 17:52:07 +0000 2009", "favourites_count" : 233, "utc_offset" : 10800, "time_zone" : "Helsinki", "geo_enabled" : false, "verified" : false, "statuses_count" : 1042, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "000000", "profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_link_color" : "CBA051", "profile_sidebar_border_color" : "000000", "profile_sidebar_fill_color" : "D4802D", "profile_text_color" : "4A2500", "profile_use_background_image" : true, "default_profile" : false, "default_profile_image" : false, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweeted_status" : { "created_at" : "Tue Apr 29 11:00:25 +0000 2014", "id" : 461097667775725569, "id_str" : "461097667775725569", "text" : "DIESELSTÖRMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e #foobar", "source" : "Tumblr", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 726763934, "id_str" : "726763934", "name" : "Black Forest Games", "screen_name" : "BlackForestTeam", "location" : "Offenburg", "description" : "South-german team that brought you Giana Sisters: Twisted Dreams", "url" : "http://t.co/BXuCnqlX50", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/BXuCnqlX50", "expanded_url" : "http://gianasisterstwisteddreams.com", "display_url" : "gianasisterstwisteddreams.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 1145, "friends_count" : 308, "listed_count" : 35, "created_at" : "Mon Jul 30 20:11:50 +0000 2012", "favourites_count" : 116, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 1475, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_banner_url" : "https://pbs.twimg.com/profile_banners/726763934/1369154494", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : false, "following" : false, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 6, "favorite_count" : 2, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 72, 94 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" }, "retweet_count" : 6, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 93, 115 ] } ], "user_mentions" : [ { "screen_name" : "BlackForestTeam", "name" : "Black Forest Games", "id" : 726763934, "id_str" : "726763934", "indices" : [ 3, 19 ] } ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" } """; // """ // }}} void matches () { var f = new Filter ("a+"); assert (f.matches ("a")); } void matches_tweet () { var acc = new Account (12345, "foobar", "Foo Bar"); var filter = new Filter ("a+"); acc.add_filter (filter); var tweet = new Tweet (); var parser = new Json.Parser (); var now = new GLib.DateTime.now_local (); try { parser.load_from_data (TD1); } catch (GLib.Error e) { critical (e.message); return; } tweet.load_from_json (parser.get_root (), now, acc); } void same_user () { var acc = new Account (12345, "foobar", "Foo Bar"); var filter = new Filter ("a+"); acc.add_filter (filter); var tweet = new Tweet (); var parser = new Json.Parser (); var now = new GLib.DateTime.now_local (); try { parser.load_from_data (TD1); } catch (GLib.Error e) { critical (e.message); return; } tweet.load_from_json (parser.get_root (), now, acc); tweet.source_tweet.author.id = 12345; // Should always return false even if the filter(s) would match assert (!acc.filter_matches (tweet)); } void links () { var acc = new Account (12345, "foobar", "Foo Bar"); var filter = new Filter ("t\\.co"); acc.add_filter (filter); var tweet = new Tweet (); var parser = new Json.Parser (); var now = new GLib.DateTime.now_local (); try { parser.load_from_data (TD1); } catch (GLib.Error e) { critical (e.message); return; } tweet.load_from_json (parser.get_root (), now, acc); // This should never match since we should be using the // 'real' url instead of the t.co shortened one. assert (!acc.filter_matches (tweet)); // ... which is also why it should match now message (tweet.get_real_text ()); acc.add_filter (new Filter ("tmblr")); assert (acc.filter_matches (tweet)); } void hashtags () { var acc = new Account (12345, "foobar", "Foo Bar"); var filter = new Filter ("#foobar"); acc.add_filter (filter); var tweet = new Tweet (); var parser = new Json.Parser (); var now = new GLib.DateTime.now_local (); try { parser.load_from_data (TD1); } catch (GLib.Error e) { critical (e.message); return; } tweet.load_from_json (parser.get_root (), now, acc); // This should never match since we should be using the // 'real' url instead of the t.co shortened one. assert (acc.filter_matches (tweet)); } int main (string[] args) { GLib.Test.init (ref args); Settings.init (); Gtk.init (ref args); Twitter.get ().init (); Dirs.create_dirs (); Utils.init_soup_session (); GLib.Test.add_func ("/filters/matches", matches); GLib.Test.add_func ("/filters/matches-tweet", matches_tweet); GLib.Test.add_func ("/filters/same-user", same_user); GLib.Test.add_func ("/filters/links", links); GLib.Test.add_func ("/filters/hashtags", hashtags); return GLib.Test.run (); } corebird-1.1/tests/friends.vala000066400000000000000000000030541260276623600166210ustar00rootroot00000000000000 void set () { Account account = new Account (1337, "Name", "Screen Name"); Json.Array friends = new Json.Array (); for (int i = 10; i <= 17; i ++) { friends.add_int_element (i); } account.set_friends (friends); for (int i = 10; i <= 17; i ++) { assert (account.follows_id (i)); } } void add () { Account account = new Account (1337, "Name", "Screen Name"); Json.Array friends = new Json.Array (); for (int i = 10; i <= 17; i ++) { friends.add_int_element (i); } account.set_friends (friends); account.follow_id (1337); assert (account.follows_id (1337)); for (int i = 10; i <= 17; i ++) { assert (account.follows_id (i)); } } void _remove () { Account account = new Account (1337, "Name", "Screen Name"); Json.Array friends = new Json.Array (); for (int i = 10; i <= 17; i ++) { friends.add_int_element (i); } account.set_friends (friends); account.unfollow_id (10); account.unfollow_id (11); account.unfollow_id (12); for (int i = 13; i <= 17; i ++) { assert (account.follows_id (i)); } assert (!account.follows_id (10)); assert (!account.follows_id (11)); assert (!account.follows_id (12)); account.unfollow_id (17); assert (!account.follows_id (17)); account.unfollow_id (17); assert (!account.follows_id (17)); } int main (string[] args) { GLib.Test.init (ref args); Dirs.create_dirs (); GLib.Test.add_func ("/friends/set", set); GLib.Test.add_func ("/friends/add", add); GLib.Test.add_func ("/friends/remove", _remove); return GLib.Test.run (); } corebird-1.1/tests/highlighting.vala000066400000000000000000000045611260276623600176400ustar00rootroot00000000000000 // UTIL {{{ Gtk.TextBuffer create_buffer () { Gtk.TextBuffer buffer = new Gtk.TextBuffer (null); buffer.create_tag ("mention", null); buffer.create_tag ("link", null); buffer.create_tag ("hashtag", null); return buffer; } // }}} void mention () { Gtk.TextBuffer buffer = create_buffer (); buffer.apply_tag.connect ((buffer, tag, start, end) => { string s = buffer.get_text (start, end, false); assert (s == "@bla"); }); buffer.set_text ("A @bla B"); TweetUtils.annotate_text (buffer); } void underline_mention () { Gtk.TextBuffer buffer = create_buffer (); buffer.apply_tag.connect ((buffer, tag, start, end) => { string s = buffer.get_text (start, end, false); message ("Underline mention: %s", s); assert (s == "@bla_foo"); }); buffer.set_text ("A @bla_foo B"); TweetUtils.annotate_text (buffer); } void normal () { Gtk.TextBuffer buffer = create_buffer (); buffer.set_text ("foobar @blabla"); buffer.apply_tag.connect ((buffer, tag, start, end) => { string mention = buffer.get_text (start, end, false); assert (mention == "@blabla"); assert (tag.name == "mention"); }); TweetUtils.annotate_text (buffer); } void hashtag () { Gtk.TextBuffer buffer = create_buffer (); buffer.set_text ("foobar #hash."); int num = 0; buffer.apply_tag.connect ((buffer, tag, start, end) => { string mention = buffer.get_text (start, end, false); assert (mention == "#hash"); assert (tag.name == "hashtag"); num ++; }); TweetUtils.annotate_text (buffer); assert (num == 1); } // Sorry for this name. void non_default_mention () { Gtk.TextBuffer buffer = create_buffer (); buffer.set_text ("“@foobar"); int num = 0; buffer.apply_tag.connect ((buffer, tag, start, end) => { string mention = buffer.get_text (start, end, false); assert (mention == "@foobar"); assert (tag.name == "mention"); num ++; }); TweetUtils.annotate_text (buffer); assert (num == 1); } void main (string[] args) { GLib.Test.init (ref args); Gtk.init (ref args); GLib.Test.add_func ("/highlighting/normal", normal); GLib.Test.add_func ("/highlighting/underline", underline_mention); GLib.Test.add_func ("/highlighting/mention", mention); GLib.Test.add_func ("/highlighting/hashtag", hashtag); GLib.Test.add_func ("/highlighting/non-default-mention", non_default_mention); GLib.Test.run (); } corebird-1.1/tests/inlinemediadownloader.vala000066400000000000000000000270361260276623600215320ustar00rootroot00000000000000 // UTIL {{{ void delete_file (string filename) { if (FileUtils.test (filename, FileTest.EXISTS)) { try { var f = GLib.File.new_for_path (filename); f.delete (); } catch (GLib.Error e) { warning (e.message); } } } // }}} void media_name () { Media m = new Media (); m.id = 5; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.author = UserIdentity (); t.id = 0; t.source_tweet.author.id = 1; m.url = "http://foobar.com/nananana.jpg"; string path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, m); assert (path == Dirs.cache ("assets/media/0_1_5.jpeg")); m.url = "http://bla.com/nananana"; path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, m); assert (path == Dirs.cache ("assets/media/0_1_5.png")); m.url = "http://bla.com/foobar.png"; path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, m); assert (path == Dirs.cache ("assets/media/0_1_5.png")); t.retweeted_tweet = new MiniTweet (); t.source_tweet.id = 10; path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, m); assert (path == Dirs.cache ("assets/media/10_1_5.png")); } void normal_download () { var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var main_loop = new GLib.MainLoop (); var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 0; t.source_tweet.author = UserIdentity (); t.id = 0; t.source_tweet.author.id = 1; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); // first delete the file if it does exist delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path != null); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); main_loop.quit (); }); main_loop.run (); } void animation_download () { var main_loop = new GLib.MainLoop (); var url = "http://i.imgur.com/rgF0Czu.gif"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 100; t.source_tweet.author = UserIdentity (); t.id = 100; t.source_tweet.author.id = 20; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path != null); assert (media.path == media_path); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); main_loop.quit (); }); main_loop.run (); } void download_twice () { var main_loop = new GLib.MainLoop (); var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 300; t.source_tweet.author = UserIdentity (); t.id = 300; t.source_tweet.author.id = 5; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path != null); assert (media.path == media_path); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { // NOTE: We are *not* deleting the just downloaded file here assert (media.path == media_path); assert (media.thumbnail != null); main_loop.quit (); }); }); main_loop.run (); } void no_thumbnail () { var main_loop = new GLib.MainLoop (); var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 300; t.source_tweet.author = UserIdentity (); t.id = 300; t.source_tweet.author.id = 5; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path != null); assert (media.thumbnail != null); assert (media.thumb_path == thumb_path); assert (GLib.FileUtils.test (media.thumb_path, GLib.FileTest.EXISTS)); // Delete the thumbnail //delete_file (thumb_path); // Download again InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { //assert (false); assert (media.thumbnail != null); assert (media.thumb_path == thumb_path); assert (GLib.FileUtils.test (media.thumb_path, GLib.FileTest.EXISTS)); main_loop.quit (); }); }); main_loop.run (); } void no_media () { var main_loop = new GLib.MainLoop (); var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 300; t.source_tweet.author = UserIdentity (); t.id = 300; t.source_tweet.author.id = 5; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (GLib.FileUtils.test (media.thumb_path, GLib.FileTest.EXISTS)); // Delete the media (not the thumbnail) delete_file (media_path); assert (!GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (GLib.FileUtils.test (media.thumb_path, GLib.FileTest.EXISTS)); main_loop.quit (); }); }); main_loop.run (); } void too_big () { var main_loop = new GLib.MainLoop (); Settings.get ().set_double ("max-media-size", 0.0); var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 0; t.source_tweet.author = UserIdentity (); t.id = 0; t.source_tweet.author.id = 1; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); // first delete the file if it does exist delete_file (media_path); delete_file (thumb_path); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { // gets set anyway assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail == null); // should be marked invalid assert (media.invalid); main_loop.quit (); Settings.get ().revert (); }); main_loop.run (); } void double_download () { var main_loop = new GLib.MainLoop (); var url = "http://pbs.twimg.com/media/BiHRjmFCYAAEKFg.png"; var media = new Media (); media.url = url; Tweet t = new Tweet (); t.source_tweet = new MiniTweet (); t.source_tweet.id = 0; t.source_tweet.author = UserIdentity (); t.id = 0; t.source_tweet.author.id = 1; t.source_tweet.medias = new Media[1]; t.source_tweet.medias[0] = media; var media_path = InlineMediaDownloader.get ().get_media_path (t.source_tweet, media); var thumb_path = InlineMediaDownloader.get ().get_thumb_path (t.source_tweet, media); // first delete the file if it does exist delete_file (media_path); delete_file (thumb_path); var collect_obj = new Collect (5); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { message ("First callback"); assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (!media.invalid); collect_obj.emit (); }); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { message ("Second callback"); assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (!media.invalid); collect_obj.emit (); }); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { message ("Second callback"); assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (!media.invalid); collect_obj.emit (); }); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { message ("Second callback"); assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (!media.invalid); collect_obj.emit (); }); InlineMediaDownloader.get ().load_media.begin (t.source_tweet, media, () => { message ("Second callback"); assert (media.path == media_path); assert (media.thumb_path == thumb_path); assert (media.thumbnail != null); assert (GLib.FileUtils.test (media.path, GLib.FileTest.EXISTS)); assert (!media.invalid); collect_obj.emit (); }); collect_obj.finished.connect (() => { main_loop.quit (); }); main_loop.run (); assert (collect_obj.done); } int main (string[] args) { GLib.Test.init (ref args); GLib.Environment.set_variable ("GSETTINGS_BACKEND", "memory", true); Gtk.init (ref args); Settings.init (); Dirs.create_dirs (); Utils.init_soup_session (); GLib.Test.add_func ("/media/name", media_name); GLib.Test.add_func ("/media/normal-download", normal_download); GLib.Test.add_func ("/media/animation-download", animation_download); GLib.Test.add_func ("/media/download-twice", download_twice); GLib.Test.add_func ("/media/no-thumbnail", no_thumbnail); GLib.Test.add_func ("/media/no-media", no_media); GLib.Test.add_func ("/media/double_download", double_download); /* Keep this one at the bottom! */ GLib.Test.add_func ("/media/too_big", too_big); return GLib.Test.run (); } corebird-1.1/tests/sql.vala000066400000000000000000000027411260276623600157700ustar00rootroot00000000000000 const string DB = "./_test.db"; // Utils {{{ int get_user_version (Sql.Database db) { int user_version = 0; db.exec ("pragma user_version;", (n_cols, vals) => { user_version = int.parse(vals[0]); return Sql.STOP; }); return user_version; } // }}} void normal () { GLib.FileUtils.remove(DB); var db = new Sql.Database (DB, "./sql_init%d.sql"); int user_version = get_user_version (db); // sql_init1.sql sets user_version to 1 message ("User version after sql_init1.sql: %d", user_version); assert (user_version == 1); } void init_file_gap () { GLib.FileUtils.remove(DB); var db = new Sql.Database (DB, "./_sql_init%d.sql"); int user_version = get_user_version (db); // user_version should be 1 (from _sql_init1.sql), not 3 (from _sql_init3.sql). message ("User version after _sql_init1.sql: %d", user_version); assert (user_version == 1); } void consecutive_init_files () { GLib.FileUtils.remove(DB); var db = new Sql.Database (DB, "./__sql_init%d.sql"); int user_version = get_user_version (db); // user_version should be 1 (from _sql_init1.sql), not 3 (from _sql_init3.sql). message ("User version after __sql_init1.sql/2: %d", user_version); assert (user_version == 2); } int main (string[] args) { GLib.Test.init (ref args); GLib.Test.add_func ("/sql/normal", normal); GLib.Test.add_func ("/sql/init-file-gap", init_file_gap); GLib.Test.add_func ("/sql/consecutive-init-files", consecutive_init_files); return GLib.Test.run (); } corebird-1.1/tests/sql_init1.sql000066400000000000000000000001411260276623600167400ustar00rootroot00000000000000 PRAGMA user_version = 1; CREATE TABLE IF NOT EXISTS `test_table`( id INTEGER PRIMARY KEY ); corebird-1.1/tests/sql_init3.sql000066400000000000000000000000321260276623600167410ustar00rootroot00000000000000 PRAGMA user_version = 3; corebird-1.1/tests/texttransform.vala000066400000000000000000000263431260276623600201150ustar00rootroot00000000000000 void normal () { var entities = new TextEntity[0]; string source_text = "foo bar foo"; string result = TextTransform.transform (source_text, entities, 0); assert (result == source_text); } void simple () { var entities = new TextEntity[1]; entities[0] = TextEntity () { from = 4, to = 6, display_text = "display_text", tooltip_text = "tooltip_text", target = "target_text" }; string source_text = "foo bar foo"; string result = TextTransform.transform (source_text, entities, 0); // Not the best asserts, but oh well assert (result.contains ("display_text")); assert (result.contains ("tooltip_text")); assert (result.contains ("target_text")); } void url_at_end () { var entities = new TextEntity[1]; entities[0] = TextEntity () { from = 8, to = 9, display_text = "display_text", tooltip_text = "tooltip_text", target = "target_text" }; string source_text = "foo bar foo"; string result = TextTransform.transform (source_text, entities, 0); // Not the best asserts, but oh well assert (result.contains ("display_text")); assert (result.contains ("tooltip_text")); assert (result.contains ("target_text")); } void utf8 () { var entities = new TextEntity[1]; entities[0] = TextEntity () { from = 2, to = 6, display_text = "#foo", tooltip_text = "#foo", target = null }; string source_text = "× #foo"; string result = TextTransform.transform (source_text, entities, TransformFlags.REMOVE_MEDIA_LINKS); assert (result.has_prefix ("× ")); } void expand_links () { /* TransformFlags.EXPAND_LINKS means: - If target != null, use the target instead of the display_text - if target == null, use the display_text - but in any case, don't add any pango markup tags */ var entities = new TextEntity[1]; entities[0] = TextEntity () { from = 2, to = 6, display_text = "displayfoobar", tooltip_text = "#foo", target = "target_url" }; string source_text = "× #foo"; string result = TextTransform.transform (source_text, entities, TransformFlags.EXPAND_LINKS); assert (result.has_prefix ("× ")); assert (!result.contains ("displayfoobar")); assert (result.contains ("target_url")); } void multiple_links () { var entities = new TextEntity[4]; entities[0] = TextEntity () { from = 0, to = 22, display_text = "mirgehendirurlsaus.com", target = "http://mirgehendirurlsaus.com", tooltip_text = "http://mirgehendirurlsaus.com" }; entities[1] = TextEntity () { from = 26, to = 48, display_text = "foobar.com", target = "http://foobar.com", tooltip_text = "http://foobar.com" }; entities[2] = TextEntity () { from = 52, to = 74, display_text = "hahaaha.com", target = "http://hahaaha.com", tooltip_text = "http://hahaaha.com" }; entities[3] = TextEntity () { from = 77, to = 99, display_text = "huehue.org", target = "http://huehue.org", tooltip_text = "http://huehue.org" }; string text = "http://t.co/O5uZwJg31k http://t.co/BsKkxv8UG4 http://t.co/W8qs846ude http://t.co/x4bKoCusvQ"; string result = TextTransform.transform (text, entities, 0); string spec = """mirgehendirurlsaus.com foobar.com hahaaha.com huehue.org"""; assert (result == spec); } void remove_only_trailing_hashtags () { string text = "Hey, #totally inappropriate @baedert! #baedertworship öä #thefeels "; var entities = new TextEntity[4]; entities[0] = TextEntity () { from = 5, to = 13, display_text = "#totally", target = "foobar" }; entities[1] = TextEntity () { from = 28, to = 36, display_text = "@baedert", target = "blubb" }; entities[2] = TextEntity () { from = 38, to = 53, display_text = "#baedertwhorship", target = "bla" }; entities[3] = TextEntity () { from = 57, to = 66, display_text = "#thefeels", target = "foobar" }; string result = TextTransform.transform (text, entities, TransformFlags.REMOVE_TRAILING_HASHTAGS); assert (result.contains (">@baedert<")); // Mention should still be a link assert (result.contains (">#totally<")); assert (!result.contains ("#baedertworship")); assert (!result.contains ("#thefeels")); } void remove_multiple_trailing_hashtags () { string text = "Hey, #totally inappropriate @baedert! #baedertworship #thefeels #foobar"; var entities = new TextEntity[5]; entities[0] = TextEntity () { from = 5, to = 13, display_text = "#totally", target = "foobar" }; entities[1] = TextEntity () { from = 28, to = 36, display_text = "@baedert", target = "blubb" }; entities[2] = TextEntity () { from = 38, to = 53, display_text = "#baedertwhorship", target = "bla" }; entities[3] = TextEntity () { from = 54, to = 63, display_text = "#thefeels", target = "foobar" }; entities[4] = TextEntity () { from = 64, to = 71, display_text = "#foobar", target = "bla" }; string result = TextTransform.transform (text, entities, TransformFlags.REMOVE_TRAILING_HASHTAGS); assert (result.contains (">@baedert<")); // Mention should still be a link assert (result.contains (">#totally<")); assert (!result.contains ("#baedertworship")); assert (!result.contains ("#thefeels")); assert (!result.contains ("#foobar")); } void trailing_hashtags_mention_before () { string text = "Hey, #totally inappropriate! #baedertworship @baedert #foobar"; var entities = new TextEntity[4]; entities[0] = TextEntity () { from = 5, to = 13, display_text = "#totally", target = "foobar" }; entities[1] = TextEntity () { from = 29, to = 44, display_text = "#baedertworship", target = "bla" }; entities[2] = TextEntity () { from = 45, to = 53, display_text = "@baedert", target = "foobar" }; entities[3] = TextEntity () { from = 54, to = 61, display_text = "#foobar", target = "bla" }; string result = TextTransform.transform (text, entities, TransformFlags.REMOVE_TRAILING_HASHTAGS); assert (result.contains (">@baedert<")); // Mention should still be a link assert (result.contains (">#totally<")); assert (result.contains (">#baedertworship<")); assert (!result.contains ("#foobar")); } void whitespace_hashtags () { string text = "Hey, #totally inappropriate @baedert! #baedertworship #thefeels #foobar"; var entities = new TextEntity[5]; entities[0] = TextEntity () { from = 5, to = 13, display_text = "#totally", target = "foobar" }; entities[1] = TextEntity () { from = 28, to = 36, display_text = "@baedert", target = "blubb" }; entities[2] = TextEntity () { from = 38, to = 53, display_text = "#baedertwhorship", target = "bla" }; entities[3] = TextEntity () { from = 54, to = 63, display_text = "#thefeels", target = "foobar" }; entities[4] = TextEntity () { from = 64, to = 71, display_text = "#foobar", target = "bla" }; string result = TextTransform.transform (text, entities, TransformFlags.REMOVE_TRAILING_HASHTAGS); assert (result.contains (">@baedert<")); // Mention should still be a link assert (result.contains (">#totally<")); assert (!result.contains ("#baedertworship")); assert (!result.contains ("#thefeels")); assert (!result.contains ("#foobar")); assert (!result.contains (" ")); // 3 spaces between the 3 hashtags } void trailing_hashtags_link_after () { string text = "Hey, #totally inappropriate @baedert! #baedertworship https://foobar.com"; var entities = new TextEntity[4]; entities[0] = TextEntity () { from = 5, to = 13, display_text = "#totally", target = "foobar" }; entities[1] = TextEntity () { from = 28, to = 36, display_text = "@baedert", target = "blubb" }; entities[2] = TextEntity () { from = 38, to = 53, display_text = "#baedertwhorship", target = "bla" }; entities[3] = TextEntity () { from = 54, to = 72, display_text = "BLA BLA BLA", target = "https://foobar.com" }; string result = TextTransform.transform (text, entities, TransformFlags.REMOVE_TRAILING_HASHTAGS); message ("'%s'", result); assert (result.contains (">@baedert<")); // Mention should still be a link assert (result.contains (">#totally<")); assert (!result.contains ("#baedertworship")); } void no_quoted_link () { Tweet t = new Tweet (); t.quoted_tweet = new MiniTweet (); t.quoted_tweet.id = 1337; t.source_tweet = new MiniTweet (); t.source_tweet.text = "Foobar"; t.source_tweet.entities = new TextEntity[1]; t.source_tweet.entities[0] = TextEntity () { from = 0, to = 6, target = "https://twitter.com/bla/status/1337", display_text = "sometextwhocares" }; string result = t.get_trimmed_text (); message (result); assert (!result.contains ("1337")); } int main (string[] args) { Intl.setlocale (LocaleCategory.ALL, ""); GLib.Test.init (ref args); Settings.init (); GLib.Test.add_func ("/tt/normal", normal); GLib.Test.add_func ("/tt/simple", simple); GLib.Test.add_func ("/tt/url-at-end", url_at_end); GLib.Test.add_func ("/tt/utf8", utf8); GLib.Test.add_func ("/tt/expand-links", expand_links); GLib.Test.add_func ("/tt/multiple-links", multiple_links); GLib.Test.add_func ("/tt/remove-only-trailing-hashtags", remove_only_trailing_hashtags); GLib.Test.add_func ("/tt/remove-multiple-trailing-hashtags", remove_multiple_trailing_hashtags); GLib.Test.add_func ("/tt/trailing-hashtags-mention-before", trailing_hashtags_mention_before); GLib.Test.add_func ("/tt/whitespace-between-trailing-hashtags", whitespace_hashtags); GLib.Test.add_func ("/tt/trailing-hashtags-media-link-after", trailing_hashtags_link_after); GLib.Test.add_func ("/tt/no-quoted-link", no_quoted_link); return GLib.Test.run (); } corebird-1.1/tests/tweet_length.vala000066400000000000000000000042751260276623600176660ustar00rootroot00000000000000 void normal () { string t = "ABC"; assert (TweetUtils.calc_tweet_length (t) == 3); } void empty () { int l = TweetUtils.calc_tweet_length (""); message ("empty length %d", l); assert (l == 0); } void http_link () { string text = "http://foobar.org"; int l = TweetUtils.calc_tweet_length (text); message ("Link length: %d", l); assert (l == 22); } void https_link () { string text = "https://foobar.org/thisissolong/itsnotevenfunnyanymore"; int l = TweetUtils.calc_tweet_length (text); message ("Https link length: %d", l); assert (l == 23); } void media () { string text = ""; int l = TweetUtils.calc_tweet_length (text, 1); message ("media length: %d", l); assert (l == Twitter.short_url_length_https); } void media_text () { string text = "0123456789 012345678"; int l = TweetUtils.calc_tweet_length (text, 1); message ("media length: %d", l); assert (l == Twitter.short_url_length_https + 20); } void tld1 () { string text = "google.com"; int l = TweetUtils.calc_tweet_length (text); message ("tld1 length: %d", l); assert (l == Twitter.short_url_length); } void real_text1 () { string text = "That @humble Bundle we're doing? Finishes in 1:40hrs so if you still want to get 7 great fantasy games dirt cheap... humblebundle.com/weekly"; int l = TweetUtils.calc_tweet_length (text); message ("real text 1 length: %d", l); assert (l == 139); // according to Twitter's web interface } void newline_link () { string text = "Foo\nhttp://foobar.org"; int l = TweetUtils.calc_tweet_length (text); message ("Length: %d", l); assert (l == 26); } int main (string[] args) { GLib.Test.init (ref args); GLib.Test.add_func ("/tweet-length/normal", normal); GLib.Test.add_func ("/tweet-length/empty", empty); GLib.Test.add_func ("/tweet-length/http-link", http_link); GLib.Test.add_func ("/tweet-length/https-link", https_link); GLib.Test.add_func ("/tweet-length/media", media); GLib.Test.add_func ("/tweet-length/media-text", media_text); GLib.Test.add_func ("/tweet-length/tld1", tld1); GLib.Test.add_func ("/tweet-length/real-text1", real_text1); GLib.Test.add_func ("/tweet-length/newline-link", newline_link); return GLib.Test.run (); } corebird-1.1/tests/tweet_parsing.vala000066400000000000000000000465031260276623600200500ustar00rootroot00000000000000 // {{{ const string TD1 = """ { "created_at" : "Mon May 05 06:48:32 +0000 2014", "id" : 463208606784311296, "id_str" : "463208606784311296", "text" : "RT @BlackForestTeam: DIESELSTÖRMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e", "source" : "web", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 62574927, "id_str" : "62574927", "name" : "Frozenbyte", "screen_name" : "Frozenbyte", "location" : "Helsinki, Finland", "description" : "We're an independent game developer. Follow us on Twitter to get the latest news on our games! For support issues please get in touch via email.", "url" : "http://t.co/NlgW9k9ZXj", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/NlgW9k9ZXj", "expanded_url" : "http://www.frozenbyte.com", "display_url" : "frozenbyte.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 5682, "friends_count" : 137, "listed_count" : 242, "created_at" : "Mon Aug 03 17:52:07 +0000 2009", "favourites_count" : 233, "utc_offset" : 10800, "time_zone" : "Helsinki", "geo_enabled" : false, "verified" : false, "statuses_count" : 1042, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "000000", "profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_link_color" : "CBA051", "profile_sidebar_border_color" : "000000", "profile_sidebar_fill_color" : "D4802D", "profile_text_color" : "4A2500", "profile_use_background_image" : true, "default_profile" : false, "default_profile_image" : false, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweeted_status" : { "created_at" : "Tue Apr 29 11:00:25 +0000 2014", "id" : 461097667775725569, "id_str" : "461097667775725569", "text" : "DIESELSTÖRMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e", "source" : "Tumblr", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 726763934, "id_str" : "726763934", "name" : "Black Forest Games", "screen_name" : "BlackForestTeam", "location" : "Offenburg", "description" : "South-german team that brought you Giana Sisters: Twisted Dreams", "url" : "http://t.co/BXuCnqlX50", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/BXuCnqlX50", "expanded_url" : "http://gianasisterstwisteddreams.com", "display_url" : "gianasisterstwisteddreams.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 1145, "friends_count" : 308, "listed_count" : 35, "created_at" : "Mon Jul 30 20:11:50 +0000 2012", "favourites_count" : 116, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 1475, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_banner_url" : "https://pbs.twimg.com/profile_banners/726763934/1369154494", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : false, "following" : false, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 6, "favorite_count" : 2, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 72, 94 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" }, "retweet_count" : 6, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 93, 115 ] } ], "user_mentions" : [ { "screen_name" : "BlackForestTeam", "name" : "Black Forest Games", "id" : 726763934, "id_str" : "726763934", "indices" : [ 3, 19 ] } ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" }"""; const string TD2 = """ { "created_at": "Tue Apr 29 00:50:10 +0000 2014", "id": 460944092554227713, "id_str": "460944092554227713", "text": "Combined. http:\/\/t.co\/fFJqqT1A4j", "source": "\u003ca href=\"http:\/\/twitter.com\/geekculturejam\" rel=\"nofollow\"\u003eCultureJam\u003c\/a\u003e", "truncated": false, "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "user": { "id": 657693, "id_str": "657693", "screen_name": "FOOBAR", "name": "Foo Bar", "profile_image_url" : "http://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "verified" : false }, "geo": null, "coordinates": null, "place": null, "contributors": null, "retweet_count": 0, "favorite_count": 0, "entities": { "hashtags": [], "symbols": [], "urls": [], "user_mentions": [], "media": [] }, "extended_entities": { "media": [ { "id": 460938773744717825, "id_str": "460938773744717825", "indices": [ 10, 32 ], "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo", "sizes": { "medium": { "w": 599, "h": 397, "resize": "fit" }, "thumb": { "w": 150, "h": 150, "resize": "crop" }, "small": { "w": 340, "h": 225, "resize": "fit" }, "large": { "w": 1023, "h": 678, "resize": "fit" } } }, { "id": 460938635315916, "indices": [ 10, 32 ], "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo", "sizes": { "medium": { "w": 600, "h": 600, "resize": "fit" }, "thumb": { "w": 150, "h": 150, "resize": "crop" }, "large": { "w": 1024, "h": 1024, "resize": "fit" }, "small": { "w": 340, "h": 340, "resize": "fit" } } } ] }, "favorited": false, "retweeted": false, "possibly_sensitive": false, "lang": "en" } """; const string TD3 = """ { "created_at" : "Thu Jun 12 19:34:16 +0000 2014", "id" : 477172048427765760, "id_str" : "477172048427765760", "text" : "http://t.co/ZGX7b9YGiU http://t.co/6hfxg0TPyt", "source" : "Twitter Web Client", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 993713617, "id_str" : "993713617", "name" : "Core Bird", "screen_name" : "corebirdgtk", "location" : "", "description" : "", "url" : null, "entities" : { "description" : { "urls" : [ ] } }, "protected" : true, "followers_count" : 1, "friends_count" : 6, "listed_count" : 0, "created_at" : "Thu Dec 06 19:47:16 +0000 2012", "favourites_count" : 12, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 537, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_image_url_https" : "https://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : true, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 0, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZGX7b9YGiU", "expanded_url" : "http://i.imgur.com/kgrtCf0.png", "display_url" : "i.imgur.com/kgrtCf0.png", "indices" : [ 0, 22 ] }, { "url" : "http://t.co/6hfxg0TPyt", "expanded_url" : "http://i.imgur.com/xqmzPar.gif", "display_url" : "i.imgur.com/xqmzPar.gif", "indices" : [ 23, 45 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "und" } """; const string TD4 = """ { "created_at" : "Thu Jun 12 19:34:16 +0000 2014", "id" : 477172048465760, "id_str" : "477172048427765760", "text" : "http://t.co/ZGX7b9YGiU http://t.co/6hfxg0TPyt", "source" : "Twitter Web Client", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 993713617, "id_str" : "993713617", "name" : "Core Bird", "screen_name" : "corebirdgtk", "location" : "", "description" : "", "url" : null, "entities" : { "description" : { "urls" : [ ] } }, "protected" : true, "followers_count" : 1, "friends_count" : 6, "listed_count" : 0, "created_at" : "Thu Dec 06 19:47:16 +0000 2012", "favourites_count" : 12, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 537, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_image_url_https" : "https://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : true, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 0, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZGX7b9YGiU", "expanded_url" : "http://i.imgur.com/kgrtCf0.png", "display_url" : "i.imgur.com/kgrtCf0.png", "indices" : [ 0, 22 ] }, { "url" : "http://t.co/6hfxg0TPyt", "expanded_url" : "http://i.imgur.com/xqmzPar.gif", "display_url" : "i.imgur.com/xqmzPar.gif", "indices" : [ 23, 45 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "und", "extended_entities": { "media": [ { "id": 460938773744717, "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo" }, { "id": 460938615916800, "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo" } ] } } """; // """ // }}} /* UTILS {{{ */ void rm_dir (string path) { try { var directory = File.new_for_path (path); var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME, 0); FileInfo file_info; while ((file_info = enumerator.next_file ()) != null) { if (file_info.get_file_type () != GLib.FileType.DIRECTORY) { GLib.FileUtils.remove (path + "/" + file_info.get_name ()); } } } catch (Error e) { critical (e.message); } } /* }}} */ void retweet () { var acc = new Account (12345, "foobar", "Foo Bar"); var now = new GLib.DateTime.now_local (); Tweet t = new Tweet (); var parser = new Json.Parser (); try { parser.load_from_data (TD1); } catch (GLib.Error e) { critical (e.message); } var root = parser.get_root (); t.load_from_json (root, now, acc); assert (t.source_tweet != null); assert (t.id == 463208606784311296); assert (t.retweeted_tweet != null); assert (t.retweeted_tweet.id == 461097667775725569); assert (t.source_tweet.author.user_name == "Frozenbyte"); assert (t.favorite_count == 0); assert (t.retweet_count == 6); assert (t.source_tweet.author.id == 62574927); assert (t.get_mentions ().length == 0); assert (t.retweeted_tweet.author.user_name == "Black Forest Games"); assert (!t.favorited); assert (!t.retweeted); assert (!t.verified); assert (t.reply_id == 0); assert (t.my_retweet == 0); //assert (!t.has_inline_media); } void media_count () { var acc = new Account (12345, "foobar", "Foo Bar"); var now = new GLib.DateTime.now_local (); Tweet t = new Tweet (); rm_dir (Dirs.cache ("assets/media")); rm_dir (Dirs.cache ("assets/media/thumbs")); var parser = new Json.Parser (); try { parser.load_from_data (TD3); } catch (GLib.Error e) { critical (e.message); } var root = parser.get_root (); t.load_from_json (root, now, acc); assert (t.screen_name == "corebirdgtk"); message ("Media count: %d", t.medias.length); assert (t.medias.length == 2); } void media_count2 () { var acc = new Account (12345, "foobar", "Foo Bar"); var now = new GLib.DateTime.now_local (); Tweet t = new Tweet (); rm_dir (Dirs.cache ("assets/media")); rm_dir (Dirs.cache ("assets/media/thumbs")); var parser = new Json.Parser (); try { parser.load_from_data (TD4); } catch (GLib.Error e) { critical (e.message); } var root = parser.get_root (); t.load_from_json (root, now, acc); assert (t.screen_name == "corebirdgtk"); message ("Media count: %d", t.medias.length); /* TD4 has 2 imgur urls in its text, that's 2 inline media. Additionally, it has 2 enties in its extended_media array, so it should have 4 inline media. */ assert (t.medias.length == 4); } int main (string[] args) { GLib.Test.init (ref args); Settings.init (); Gtk.init (ref args); Twitter.get ().init (); Utils.init_soup_session (); GLib.Test.add_func ("/tweet-parsing/retweet", retweet); GLib.Test.add_func ("/tweet-parsing/media-count", media_count); GLib.Test.add_func ("/tweet-parsing/media-count2", media_count2); return GLib.Test.run (); } corebird-1.1/tests/tweetmodel.vala000066400000000000000000000077331260276623600173500ustar00rootroot00000000000000 void basic_tweet_order () { TweetModel tm = new TweetModel (); Tweet t1 = new Tweet (); t1.id = 10; Tweet t2 = new Tweet (); t2.id = 100; Tweet t3 = new Tweet (); t3.id = 1000; tm.add (t3); // 1000 tm.add (t1); // 10 tm.add (t2); // 100 assert (tm.get_n_items () == 3); assert (((Tweet)tm.get_item (0)).id == 1000); assert (((Tweet)tm.get_item (1)).id == 100); assert (((Tweet)tm.get_item (2)).id == 10); } void tweet_removal () { var tm = new TweetModel (); //add 10 visible tweets for (int i = 0; i < 10; i ++) { var t = new Tweet (); t.id = 100 - i; tm.add (t); } // now add 2 invisible tweets { var t = new Tweet (); t.id = 2; t.hidden_flags |= Tweet.HIDDEN_FORCE; tm.add (t); t = new Tweet (); t.id = 1; t.hidden_flags |= Tweet.HIDDEN_UNFOLLOWED; tm.add (t); } // We should have 12 now assert (tm.get_n_items () == 12); // Now remove the last 5 visible ones. // This should remove both invisible tweets as well as 5 visible ones // Leaving the model with 5 remaining tweets tm.remove_last_n_visible (5); assert (tm.get_n_items () == 5); } void clear () { var tm = new TweetModel (); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); tm.add (new Tweet ()); assert (tm.get_n_items () == 8); tm.clear (); assert (tm.get_n_items () == 0); } void remove_tweet () { var tm = new TweetModel (); var t1 = new Tweet (); t1.id = 10; tm.add (t1); var t2 = new Tweet (); t2.id = 100; tm.add (t2); assert (tm.get_n_items () == 2); tm.remove (10); assert (tm.get_n_items () == 1); tm.remove (100); assert (tm.get_n_items () == 0); } void remove_own_retweet () { var tm = new TweetModel (); var t1 = new Tweet (); t1.id = 1337; t1.my_retweet = 500; // <-- t1.retweeted = true; tm.add (t1); for (int i = 0; i < 50; i ++) { var t = new Tweet (); t.id = i; tm.add (t); } assert (tm.get_n_items () == 51); tm.remove (5); assert (tm.get_n_items () == 50); // should not actually remove any tweet tm.remove (500); assert (tm.get_n_items () == 50); } void hide_rt () { var tm = new TweetModel (); var t1 = new Tweet (); t1.source_tweet = new MiniTweet (); t1.source_tweet.author = UserIdentity (); t1.source_tweet.author.id = 10; t1.source_tweet.id = 1; t1.retweeted_tweet = new MiniTweet (); t1.retweeted_tweet.id = 100; t1.retweeted_tweet.author = UserIdentity (); t1.retweeted_tweet.author.id = 100; tm.add (t1); tm.toggle_flag_on_retweet (10, Tweet.HIDDEN_FILTERED, true); assert (tm.get_n_items () == 1); assert (((Tweet)tm.get_item (0)).is_hidden); tm.toggle_flag_on_retweet (10, Tweet.HIDDEN_FILTERED, false); assert (!((Tweet)tm.get_item (0)).is_hidden); } void get_from_id () { var tm = new TweetModel (); var t1 = new Tweet (); t1.id = 10; var t2 = new Tweet (); t2.id = 100; tm.add (t1); tm.add (t2); assert (((Tweet)tm.get_item (0)).id == 100); assert (((Tweet)tm.get_item (1)).id == 10); var result = tm.get_from_id (10, -1); assert (result != null); assert (result.id == 100); } void min_max_id () { var tm = new TweetModel (); var t = new Tweet (); t.id = 1337; tm.add (t); assert (tm.lowest_id == 1337); assert (tm.greatest_id == 1337); } int main (string[] args) { GLib.Test.init (ref args); GLib.Test.add_func ("/tweetmodel/basic-tweet-order", basic_tweet_order); GLib.Test.add_func ("/tweetmodel/tweet-removal", tweet_removal); GLib.Test.add_func ("/tweetmodel/clear", clear); GLib.Test.add_func ("/tweetmodel/remove", remove_tweet); GLib.Test.add_func ("/tweetmodel/remove-own-retweet", remove_own_retweet); GLib.Test.add_func ("/tweetmodel/hide-rt", hide_rt); GLib.Test.add_func ("/tweetmodel/get-from-id", get_from_id); GLib.Test.add_func ("/tweetmodel/min-max-id", min_max_id); return GLib.Test.run (); } corebird-1.1/tests/usercounter.vala000066400000000000000000000037501260276623600175500ustar00rootroot00000000000000 void order () { FileUtils.remove (Dirs.config ("accounts/test-account.db")); var db = new Sql.Database (Dirs.config ("accounts/test-account.db"), Sql.ACCOUNTS_INIT_FILE); var counter = new UserCounter (); counter.load (db); counter.user_seen (2, "baedert", "BAEDERT"); counter.user_seen (2, "baedert", "BAEDERT"); counter.user_seen (0, "Darth", "Vader"); counter.user_seen (5, "Party", "Time"); counter.user_seen (5, "Party", "Time"); counter.user_seen (5, "Party", "Time"); counter.user_seen (5, "Party", "Time"); int num_results; UserInfo[] infos = counter.query_by_prefix ("", 200, out num_results); message ("Results: %d", num_results); assert (num_results == 3); // They need to be sorted from highest-scoring to lowest-scoring // XXX This is currently broken int last_score = int.MAX; for (int i = 0; i < num_results; i++) { //assert (infos[i].score <= last_score); XXX last_score = infos[i].score; } } void count () { var db = new Sql.Database (Dirs.config ("accounts/118055879.db"), Sql.ACCOUNTS_INIT_FILE); var counter = new UserCounter (); counter.load (db); counter.user_seen (0, "baedert", "blabla"); int changed = counter.save (db); message ("Single change: %d", changed); assert (changed == 1); assert (counter.save (db) == 0); counter.user_seen (1, "baedert", ""); counter.user_seen (1, "baedert", ""); changed = counter.save (db); message ("Double change: %d", changed); assert (changed == 1); assert (counter.save (db) == 0); counter.user_seen (2, "baedert", ""); counter.user_seen (3, "baedert", ""); changed = counter.save (db); message ("Two users changed: %d", changed); assert (changed == 2); assert (counter.save (db) == 0); } int main (string[] args) { GLib.Test.init (ref args); Dirs.create_dirs (); GLib.Test.add_func ("/usercounter/order", order); GLib.Test.add_func ("/usercounter/count", count); return GLib.Test.run (); } corebird-1.1/tests/utils.vala000066400000000000000000000016011260276623600163230ustar00rootroot00000000000000 void file_type () { string p = "foobar.png"; assert (Utils.get_file_type (p) == "png"); p = ".hidden.bar"; assert (Utils.get_file_type (p) == "bar"); p = "foo"; assert (Utils.get_file_type (p) == ""); p = "some.pointy.name.txt"; assert (Utils.get_file_type (p) == "txt"); } void time_delta () { var now = new GLib.DateTime.now_local (); var then = now.add (-GLib.TimeSpan.MINUTE * 3); string delta = Utils.get_time_delta (then, now); assert (delta == "3m"); then = now; delta = Utils.get_time_delta (then, now); assert (delta == "Now"); then = now.add (-GLib.TimeSpan.HOUR * 20); delta = Utils.get_time_delta (then, now); assert (delta == "20h"); } int main (string[] args) { GLib.Test.init (ref args); GLib.Test.add_func ("/utils/file-type", file_type); GLib.Test.add_func ("/utils/time-delta", time_delta); return GLib.Test.run (); } corebird-1.1/ui/000077500000000000000000000000001260276623600135735ustar00rootroot00000000000000corebird-1.1/ui/Makefile.am000066400000000000000000000000341260276623600156240ustar00rootroot00000000000000EXTRA_DIST = style.css *.ui corebird-1.1/ui/about-dialog.ui000066400000000000000000000016041260276623600165020ustar00rootroot00000000000000 corebird-1.1/ui/account-create-widget.ui000066400000000000000000000153421260276623600203150ustar00rootroot00000000000000 corebird-1.1/ui/account-dialog.ui000066400000000000000000000320721260276623600170270ustar00rootroot00000000000000 corebird-1.1/ui/account-switcher-entry.ui000066400000000000000000000037111260276623600205550ustar00rootroot00000000000000 True False True False False True 0 True False center label False True 1 True True True center center none True False 0 list-add-symbolic False False end 2 corebird-1.1/ui/compose-window.ui000066400000000000000000000160421260276623600171070ustar00rootroot00000000000000 corebird-1.1/ui/dm-list-entry.ui000066400000000000000000000101171260276623600166420ustar00rootroot00000000000000 corebird-1.1/ui/dm-page.ui000066400000000000000000000062141260276623600154470ustar00rootroot00000000000000 corebird-1.1/ui/dm-placeholder-box.ui000066400000000000000000000035361260276623600176070ustar00rootroot00000000000000 corebird-1.1/ui/dm-thread-entry.ui000066400000000000000000000102451260276623600171400ustar00rootroot00000000000000 corebird-1.1/ui/dm-threads-page.ui000066400000000000000000000026341260276623600171010ustar00rootroot00000000000000 corebird-1.1/ui/filter-list-entry.ui000066400000000000000000000125551260276623600175370ustar00rootroot00000000000000 False corebird-1.1/ui/filter-page.ui000066400000000000000000000066161260276623600163420ustar00rootroot00000000000000 True False Users corebird-1.1/ui/image-crop-dialog.ui000066400000000000000000000065171260276623600174230ustar00rootroot00000000000000 corebird-1.1/ui/list-list-entry.ui000066400000000000000000000156301260276623600172220ustar00rootroot00000000000000 False corebird-1.1/ui/list-statuses-page.ui000066400000000000000000000514411260276623600176750ustar00rootroot00000000000000 True False True False Confirm True corebird-1.1/ui/lists-page.ui000066400000000000000000000005211260276623600162000ustar00rootroot00000000000000 corebird-1.1/ui/load-more-entry.ui000066400000000000000000000033661260276623600171600ustar00rootroot00000000000000 corebird-1.1/ui/main-widget.ui000066400000000000000000000036171260276623600163460ustar00rootroot00000000000000 corebird-1.1/ui/main-window.ui000066400000000000000000000123501260276623600163640ustar00rootroot00000000000000 true bottom account_button true in 6 true true none corebird-1.1/ui/media-dialog.ui000066400000000000000000000121441260276623600164500ustar00rootroot00000000000000 corebird-1.1/ui/menu.ui000066400000000000000000000011651260276623600151010ustar00rootroot00000000000000
Settings app.show-settings About app.show-about-dialog Quit app.quit
corebird-1.1/ui/modify-filter-dialog.ui000066400000000000000000000130761260276623600201500ustar00rootroot00000000000000 corebird-1.1/ui/modify-snippet-dialog.ui000066400000000000000000000117451260276623600203460ustar00rootroot00000000000000 corebird-1.1/ui/new-list-entry.ui000066400000000000000000000125351260276623600170410ustar00rootroot00000000000000 corebird-1.1/ui/profile-page.ui000066400000000000000000000566211260276623600165160ustar00rootroot00000000000000
Write Direct Message user.write-dm Tweet to @foobar user.tweet-to Add to/Remove from List user.add-remove-list
Blocked user.toggle-blocked Retweets disabled user.toggle-retweets
corebird-1.1/ui/search-page.ui000066400000000000000000000077001260276623600163150ustar00rootroot00000000000000 True False 6 6 True 0 Tweets True False 6 6 True 0 Users corebird-1.1/ui/settings-dialog.ui000066400000000000000000000534331260276623600172370ustar00rootroot00000000000000 20 2 0.1 1 true main_stack corebird-1.1/ui/start-conversation-entry.ui000066400000000000000000000154421260276623600211440ustar00rootroot00000000000000 corebird-1.1/ui/style.css000066400000000000000000000116251260276623600154520ustar00rootroot00000000000000.image-overlay{ padding-right: 5px; padding-top: 2px; } .avatar-round { border: 1px solid grey; border-radius: 48px; } .account-button { padding: 2px 4px; } .sidebar { -GtkWidget-window-dragging: true; } .button-slim { -GtkButton-default-border: 0; -GtkButton-default-outside-border: 0; -GtkButton-inner-border: 0; -GtkWidget-focus-line-width: 0; -GtkWidget-focus-padding: 0; -GtkButton-image-spacing: 0; padding: 4px; } .inline-media { background: none; border-radius: 0px; -GtkButton-default-border: 0; -GtkButton-default-outside-border: 0; -GtkButton-inner-border: 0; -GtkWidget-focus-line-width: 0; -GtkWidget-focus-padding: 0; padding: 0px; box-shadow: none; opacity: 0.8; border-top: 2px solid transparent; border-bottom: 2px solid transparent; border-left: none; border-right: none; } .inline-media:hover { border-top: 2px solid #4a90d9; border-bottom: 2px solid #4a90d9; opacity: 1.0; } .image-placeholder { background-image: none; border-radius: 0px; box-shadow: none; border: none; background-color: alpha(grey, 0.7); -GtkButton-default-border: 0; -GtkButton-default-outside-border: 0; -GtkButton-inner-border: 0; -GtkWidget-focus-line-width: 0; -GtkWidget-focus-padding: 0; -gtk-icon-source: -gtk-icontheme("list-add-symbolic"); } .image-placeholder:hover { background-color: alpha (#333, 0.8); } .image-placeholder:active { background-color: alpha (#333, 0.9); } .image-added { box-shadow: none; background-image: none; border-radius: 0px; border: none; background-color: transparent; } .image-added:hover { color: white; background-color: alpha (red, 0.34); icon-shadow: none; -gtk-icon-source: -gtk-icontheme("edit-delete-symbolic"); } .image-progress { box-shadow: none; background-image: none; border-radius: 0px; border: none; background-color: transparent; color: white; -gtk-icon-source: -gtk-icontheme("content-loading-symbolic"); } .image-success { box-shadow: none; background-image: none; border-radius: 0px; border: none; background-color: transparent; color: white; background-color: alpha (green, 0.5); -gtk-icon-source: -gtk-icontheme("object-select-symbolic"); } .image-error { box-shadow: none; background-image: none; border-radius: 0px; border: none; background-color: transparent; color: white; background-color: alpha (red, 0.5); -gtk-icon-source: -gtk-icontheme("dialog-error-symbolic"); } .retweet-button, .favorite-button, .reply-button, .more-button{ background-color: transparent; } .retweet-button:hover, .retweet-button:checked { color:green; } .favorite-button:hover, .favorite-button:checked { color: shade(yellow, 0.9); } /* Don't target :hover:active here */ .favorite-button:checked, .retweet-button:checked { background-image: none; background-color: transparent; border-color: transparent; box-shadow: none; } .reply-button:hover { color: blue; } .favorite-button:backdrop, .retweet-button:backdrop { background-color: transparent; } .badge{ background-color: shade(blue, 1.4); background-image: none; text-shadow: 0px 1px 1px #FFF; border-radius: 20px; border: 1px solid white; padding: 3px 2px; } .badge:backdrop{ background-color: transparent; } .tweet { border-bottom: solid 1px alpha (grey, 0.3); } .text-only-button{ font-weight: bold; background-image: none; background-color: transparent; border:none; text-shadow: none; -GtkButton-default-border: 0; -GtkButton-default-outside-border: 0; -GtkButton-inner-border: 0; -GtkWidget-focus-line-width: 0; -GtkWidget-focus-padding: 0; padding: 0px; box-shadow: none; border-radius: 0px; border-bottom: 1px solid transparent; } .text-only-button:hover{ border-bottom: 1px solid currentColor; } .text-only-button:active{ background-color: shade(currentColor, 2.3); } .text-only-button:backdrop{ background-color: transparent; } .readonly-text-only-button { color: currentColor; } .pixbuf-button { padding: 0px; background-image: none; background-color: transparent; border: none; border-radius: 0px; box-shadow: none; transition: box-shadow 0.2s ease-in-out; } .pixbuf-button-round { border: 1px solid grey; border-radius: 48px; } .pixbuf-button:hover { border: 1px solid #4a90d9; } .pixbuf-button:active { box-shadow: inset 0px 0px 3px alpha(black, 0.95); } .pixbuf-button:backdrop { background-color: transparent; background-image: none; } .reply-indicator { background-color: #4a90d9; } .profile-button { background-image: none; background-color: alpha(white,0); box-shadow: none; border: none; border-radius: 0px; } .profile-button:checked { border-bottom: 2px solid #4a90d9; } .profile-button:hover { background-color: alpha(white, 0.3); } .profile-button:active { background-color: alpha(white, 0.5); border-bottom: 2px solid grey; } .quote { border-left: 3px solid currentColor; padding-left: 6px; } corebird-1.1/ui/tweet-info-page.ui000066400000000000000000000416031260276623600171310ustar00rootroot00000000000000
Quote tweet.quote
corebird-1.1/ui/tweet-list-entry.ui000066400000000000000000000435021260276623600173760ustar00rootroot00000000000000
Quote tweet.quote Delete tweet.delete
corebird-1.1/ui/user-filter-entry.ui000066400000000000000000000153231260276623600175360ustar00rootroot00000000000000 False corebird-1.1/ui/user-list-entry.ui000066400000000000000000000111411260276623600172160ustar00rootroot00000000000000 corebird-1.1/ui/user-lists-widget.ui000066400000000000000000000076271260276623600175410ustar00rootroot00000000000000

t󈀥魺%yO%1{@XֺZJHCgpklY׷k=V<҅-ȐOMBIt!Hɪ=dLKdDž)*ϑkV 02P+r  w6Hv:[ݦ v"2PYESRO)\ѩP!@!nG$gf~.@ho+ئ(cW_`8HڣOhRCѸ\ Ih$4Zۦ 5J}$$%Y 1ės[c9#FaRkb(0$/NDi\1[K DRʂrR*Esr׫c[ QFzoOR3$kk;^|1 8&EDZNv2IP1]dE#ZKAڗ iKU H습7x}sEQ)Jb`<|p'CuLVDkZh76rSV=DAQPܦm&#> VKG+\12}7n$j EiY&@][VcSl&^IJt6<%3|A,Ir3}G\n E#IpH#vx _qJ̲ӫq>޵;)"/6өuE&3rVxQK"YgmWkψGAA~ Y ږժ~;wĉ.9ГKxr5WS!$8ȥc^h4GXz% d[T|x=3HOnTq4 h-oYߣ[Āpu;>cjo~]I%jK\'jQ-BSI~VucZ(=G䄄S`E%2 ֙(KKRRsyfgqiwX B\55%lZ8SWji-H?B^Y:/ibх?Ƞ>ǖcY釛ľGI _R^9VHrck }U SiSE9Żom @[1D[<.n_Z+I|8=>55n5`oh@WWmM-CZ}әNA4/r\3mLH~Pr2H?Rm&\p:1FlM>=*ZЂ~Q}^.7M,\Zei')?%= AឪO+Jl6DRH3v)S22 JJ=V 5qR'JNBr؉b5ޭ`:cGQ@)/&j9rwCPKt3Οc:rG7|`aBHlrA?EUxBBVc$)XP)dmLI?x:UwO掭 XRSOPŒw>(+v܉SO*E[/n^d7΢sԓXr~_L6UM 0JGPk45<C/r.41&<4Dl:*FN>&(_A|eOf@?◍Ӡ/K;ehfx3~W9a0B)M z ȶ6mv#LbI'Rh:p06٭tKJFoT "JjhA hVvBE{0>r}tձ;y#.ahHʃWސIu~&>Rg³N?E~ǦRW$>Lv'\y\ tslt~[C:nl֕kCIhś3] TXUJzN46em+k!HU>NB%􋴣XpyG9_˽3uϜv(1͆O%|>Lɳ>_E|4[[6c-r:mi%ivO5,7I,FM!،K۸YW3S}cj6֑AI5K"CP-q*ps~5埊FY3=Sh8hWmM,f%k; P-[QHܡHJmГp ,K܎8^rQ\xW~+7)4}N?u6_{= {! vN=JKrVztx~Y,\R"20#e84JL\^U¢P5d^_]ixii{+!Thě%7BPKx(-|\mnJcp 29tdwHRz@h [,%[u,Hy 0!:7|)vRm26+RXͩzq Z}]p2I0#6V<ݱ~qȌ瀽2CvŨ 8}ꢂuD];G'&Dt饆<V\1Lj .:\GWo+- O,#hV7a֘UfRL `j M>HBzuaM/̒”!Ջ6NLB$J1Ä%qŵמ8f᭶ J)ZLM}1mb[ӆYB 9KQ]F FO"bcŸ+Jvn!QVy|ΦUT}5nlAc=/ẏ$6+L.<75>{fB8tj-e̓,xʱO%pvpaAv)v.;&G ,G8ʱ=i{oTӖ>(tq! 78;Y1}"8a\J+GoEP1)dsZfMsTXW@3SkLõ\j\RTYQV6k pvs[ZRjZ .vJ-l6Ȩ3\"pQCt)2@=R}usB&c*I MJyǞԷ/ۭ-H.('jS\Y[ן#@UP@P \i%Ɛަ抷uuQBMTp4U|r,i(›սEpeqqMEItȈkH?Y95UMӈoU G%ď% bOԗN\@LQ(FVF=(a< W5TgdI84lNXZ jbk'eOٴ%'3Dн}pOq1f`I!^V_RX5f3 u|є[t8rRFQ #Rc|î )Y$ )A ʍ.XSRv;ep~8I{ 7캑e2ہ] 9F<*%PZ|ujoٞ9t?$[\ (ӵɶ,eD6$g%ف^ K`|i*UBWbtWNQ3FMt:RT_mPd7.˺i1m_F-W 6y+eNJs%65mV96S`+Ԗ+%-ti8*. hNȉC +en:8c?GF; n:-5ya%NeY۔;?L@D)٨ I^4݆d6RT)$JnB))HȫBdfvI+RM렌]Q2B.$lցcW{ +bd7 ۝B)BV4Q@孅iį=GZ+h Nr`!{(TE.S@zjKN>̷' _aS#DЙ{Iќ)pg)ȭ "23[ki0ǑtnI,rOJ!J@A}mδDk} <~4c#).RZ7 lMRQ-#d|^ԚP4⡗BqV7x1,jҷ43b(n@XI::{Wt[xT3E4G69{7CO8kJ5{צr4Kyg=E 95+%s @ES # /|3|yt:J7ÛƩ{/!1@ONldeiĄIx4I@ |6ش)NGz$gZ ));V93~>K̎m =#r\#`y;Q\h)*|<[aʟ+N$=;mX M. 4ZY8RthfIXU_N_(!WH-/#4|baĨ>*A㕮J|6$VT>Y%-0A1 a汐zEcSNUzP쑓ɓKvlSzYrnouqY=w$7!ȣ +&#lF6؃ܾRcf6HgFk+VF"d*)6tb0o: " h$ol~|s<G:0jч/Lv,cloFylnqNl5 Tx_/&G*t|23]b-VGi+qAɑ¡&;gbYYIQiOJ>_XJB]x_eJZgn$!mV͕B;b^̐T}b1Ej.Vc[vdͺ!g=Jv,v7n -&+>}sub;Zi4A0!:`?=X=ΐ*6c[b,DˍEaV:ziO(L)>SŹ̀{ҒӾE]ڧ)%O8*EVE3͚ Kl#F.o<@:6KKlQFpK詵 &_.ǐ Sc3t^9 B*8C.q4[pJ,eyN8WOl4iM)ţE2м.K\Ω;ObwZ8Z>DUi|f=|)?i5ȹ(olv#;kiX vJ.2;]!jAjp!eJJN|8"iD{ӜVT;R%|s&q^%.3i~NH! i-ܟ&ʅk%((^j9{BAR|LSh? /y8W0O ؤX욷$ɵMr($*Trkl\y)\wU,4)J2qy\@JI>,=#npJ',I qZYXFiQѲg.\~ q7gY,ToƉv^y N(Am/iAZ'uk X;UHd^/ats%=՚8.;+-^(rZf_OA˵5Kq$3Av%( JM'9jd<십V;4><\%KCJ;gɊfj1c~~˨alw,aC4QFJ2VĉmXN ;rϲ}.sTv|Œ=W $!oև4fƯ`ntPYO0+\ lZ;~2U?fL7jvI~ʱIc+1mPqG|ktdИvHNdRIUEJݨY4##J45 7nB@؍DH6Ȅ$> [erڳo) `)V2 P.d65k$hQ j6!Ls+ }#'hb~UhW3G$c[Qu<> w&9m( }I/e⓸yYijjtHغ-(f-K 3u]w9?؞vACm'!uBBP4(Պ$ۅ,7yY|ɓj[d)Y ҂0F+ dm QYiUR: )2wV)+3%OBmpz j;iend{4=ƣl'?$c|p<8X /++CW0I^A%8? `T|49MQ:#.8TsƟ/ˋMv h&2dASq޹Lȼzh%0Ьt(26'%olҤ梣3E6lwrtɡ~iR+En*;(,A\4UL=s5o$_c\1nN.Gq%6%#ѥSЬ/CUě`LUА;B7v_- ^" \=i$yk[YaHߐ46̹2K$re+9.yR^xe6R6-fP;w8✵RP?dQL+R;y#t9NK2E /7FP\pj\M~M(}ҕr/;,RqNJ)D̖p)$>UV1L?pQOʾP,c™ C qeo!]rRڔmNR%8YU۫(,9!;E% cIijyUgx\q#ᚭbkvuHu'@AF[!]ì|)5{SUw6r?L?b$"G-"J'5ڌė,U[GX$2}J |t~<ޙ|M2ҧJ@ykT*LpMXKs V6mj|:4Il*lBY_iH#~-ɈxS_K).j0.kmu=)T';t,YvĜk8$OF\ᶘr8YѺ8"RpVeSuIS!OO] N$\fB|,? qbq Hz+ʲG3Odz 5v$F|?@K.HH@ jϒ!m3}Jܮyѽ` MX˜Z\%Ak7k2a,⥡CpfߠZӯ-iN+=z>I_$Р5~[y=JjhF3-Khz:ԁԲ8g>#O{MEVSFqʊQBꚍfL@]:QVWzHVJ[ wЅk:f"𐳿˔e]{&niwj)5SwGIEW zZǙM9+`3 y!A9:f/`K/"';LY,L4 HPm+jIk5ӌI3)k> ?c}E;@ˍ{2wJZjٜ^w9ucbH=h?iZ|fčqsdU9*JA J%Gwx\Y-:6/s_G%U0Ry MY镒2RV()>\ѓ%ž;W~Ři*|mErY_J(Q}5R^[D\TGSZEAFRD2v@V@v-4nYs3m⑊YF,uZ6GV(ƠO`:SC*D& d41ۦ=Jhc "sKah$ۤ楙Px*ĸLs7#.A$Z3EaRg /HZIB5Ztg::KwR3kRB$}sl7O^Ck2 _U̫VWZ9Ƒdn6ZYPඤU/iD$%AJBza4h8dGM6Bj<y48E&kۉ/$T7$s >x)Qo Fg%ISH9Qn}#Ԅ!\mfbEׄw}$~/ )U.UAWXfd !;seF7ir\c XnM M,kJUrI(X=paCi'?hQ.  [o{d^TBӅb0|ub^O\'q"VQ*}RjXor}FkndE%8E\} 5h{K$ p9#S"AXE+JRPMSB'NFZ\+d1 SO5(Qd'4['Hxqu1҆e K2٬]ywTrFG7)v%/(dkg,olG,Mf,rre9]w1r.>!É3 ½B#~ÊzPf!L)Oj TGYAԑH[R5`\sed$6}a\Qz䡚CSzaUqPZ'`,b$Lǻ IqqACɿ@.[ qC%۸m~ZRڼ2{::;YlCK= ;&Q^m.;Nꓒt\QR&dy>N.ԨCr0#&;wD?ԎapBd>^l~3\>Ncq#\?ghܪk-YHuԘ댲ph "prf2b@z |r䴑ӥ)h-j{$tI~@|hx߰BT+^7ŅUZWduj+MJ IYXjATHrg&zrFY;c!Rd2˧A Y ouoja\?cΎ9RYmDO$LLyE'r"M34|/$Aa%@r2CZ*2>BG#ywNvpIΜA ZYǝ 4 97 R(:3 ;o 9UFƐ A~4Ad$;6APj)Ij͐c5*R6jv hl@)t4(Ă1%6IމHK);yɞQA/r(:TOя$-PN G&ꦎl%M&yG]#.Y9C n25=&(ZZdGds(~CE|QDvSцΒNxՐþqk y~2>tІl6$=#upcKvBϥS59d{cZ+!a?U#yn jQ]ZAەD⣄Y#9$2lJ[8=xwkqou V3Y ښ&@3s$ RqⱵ7Ok`<)Ncc(XjdͦCP0C͠g*/$%ñ Upը\lxnvR(6kW7.iVtrci?ψӷ4TtstIp|VSC>roĈԐy=i~7lfMMjC ph=̖u{=6I_PH~-[bÆqe8( )+BVTJb lF΅7L`8 r)EHޟj` `kK\auHI?;+MC-DHt+Gj˳#8[Y5 I<2#z!qCh++g>"V(I. :hsFKl%.:ns*%JN]I;]a6yr2:ӷphTttBF ,JLֵJO;.;gl,__dOzB6ӛ _v8auiSm{O #![u;^4@R\'G^kk&:,h1s}X,.}\Y+_ՄHm=" Lko7Crlt(n$R6G䗴k jtޟhlV=y%ބq;Q3 :'"IKF)^u+J`cKpv6({z_h_pl(qFsA3ʘi䅧4G;\B P{WƆSj5 % 2q84\2k%@@:H_C佑u6Rʦ=2/Й {g'+֜Q:.sb\ y8N+5#{ƜQ”Pvvn~tKhK#dllNoiQ(UXj6 n,6C>|@ Ⱥ-:n&w'I gq@ 6W.r^Ht0t`횬̄Fifx^<PTd&ϼi=5ȡF~nVdeXPm ۗZD>\9+7n^) )G7wgMyx9Z_R|VR%L4`־ca=AWKH?gJV3[pݓ"I%V؆Ji$= EH#(XH?lpw #6E9R~cȐƗc7P$ ;Kj9jKc%KTCvT($i Q-W )@s] ;QLQ=j voCccҧBEt!@f4󍩇Df}ҨOyuUq<&"(Pz$V誁g+Ib6>CMI)XqN~yE^? #S'`>?*k"cNo2*D8(Nt.:Εr-{"75Nݝ,PX6 YuXg|VyrjV=Pe*ۨG4|xcd6~#9>u#¹qHl 9j dl om\S1'j:>\797pTʽʊH򓓲ҷ&m|wv{}CIlВdd)Ф {X1IgBbc 2bSNƸ&^YSm<`֕1 m}TP=-'tf|0<9mLrr]qiDe#~RʥA=!PC `(J U Q΢۝RLvƫjϊ2FRRh% -|XFK\(9_)\U3wYf;*;kdWqh rA)}!ŏ ׅcfҥcÚFpKk'r$,=ɦTAzPRB[i&RIvYv0m䒠7mcXR^RK?Xt◰1!Ǖ!)[P8Ɏg9)QS٭ 2HQR\SM,D3,S@\%9Jq՜~Fv'}&+X5>oC7q֙enakwdPnbh]OF4 \u4#33=2f|-8G@WK串 Zh Z̟bkdM ~ƅ!H~NjJ(J=dMSf)<*O\TPMqq.8ӍIOld~5:P2Y8 Ё܌GRųq-0zKѥj#|eT&jfv$Ħ)E6ѭ*i&Z1Co{S3J")em)zdW~z*V0NA@} M{$خ7$-ʣrhjH .#Y;GAG *x@W+hy!(#L=xKsP5%E/Du >Q|37hJnŵwrqv/j_-ڷ0ʪZyB;CiHOlIN vkH*XN~YnX6K+OǵA3elcC"#N_| ?X*tHK(՚\iV7Q 7B$pv2<HڹVtn 唃[MIp+;+)y#,_.1%O*؎ԘTфt kmB&"ISYH #mq x Lf.n V VYdn[Af$T>٪8 1X ԴceIYT z%蔋R[9}" L$PۮJ`Jv*vP`ApaH 41+$|c?Wu41ZIcچOk%8 U!R>Iw4B[yB'lT']PFqL|ݢc\wڇy4xW uyuj eD1R¤_T '+< UG~+fHt/#ncC4{Ik}mZl[XYV2H5ƠliH(I9=H LTfHHgG>9nf vߕ􅫙׊ >KFhdP`~1+7d{#_etPǀJT}u/5/]EįM\Jpy;tL>6w&#D]2L'ZUZ5!CjX &nr?4XN#Bq@, )DHiS$/SD{PgZR(5\@V}/R Fw ™,V>y 8atnd0sScZK <4!S"O6] "Nb ̶GM/ءO_ژx³$'$mTᡧBGR6Kllrb8x)o:9\Y.n8Y"-pKjWbArIn`hL:'o#x?Q)nf,Q RdSV.1+P駲D M 6;8)t!;q)JGq x)pI4_(tKV=$+&Z[r|7'S)t\]S*LwTA] x.b[Ih1FivĒx^CCO/9!8C -&6u/<#IZF%Ĺ`(fW_ vxmHPV E;A4psÄn2(Wi;P%Tg3dҿB%fH!rY?]hybe-7Z+^$yKq>% g"i_t6QpS62{<`Րfw(=ƅ/M>Bp} ܅p=UɱxW3#O\zs`+U gO_, dj?)c|FJ0zvgďxnrr}yfPEFT4I*,5śhAJ+ {] I z›& V vT-euVV$vƁtS &mJ1A w`isÜsEF}zJ-tIYN_uj`Yi6Ӗs3 83SqqGA1e,BA6j&dBu-2KEgr&9YrzyIZko .[ r⠽}+3MFesiFԖyvk%k 8;#T@8UoW/'2_N TG:G&XSg3**eI9Iڶdq9m v6͂~U05Ii@l\FJ#,j OƩKZ.JYCshBPX *5jrvqC#'NA8Y%mf9v:ygߩl(k,QǨ,;znXHN:tβ X46r @zb̲Gpȉr'#;NRwFgɭ; Q(jQ..HqChkQ܊6!&:>T!} dƀq#De|"̔#bzT2NUc͆Qlԣj߫ h۳"2*g63ӈWZqIuǔ4xl>hZY uJ:`yGG19s./'`(JvHY~ͯ6Fp!!Mr{4&0WOk#(\I8)8__RCCl'wײ>fHݍZndMS:&喼=LpʖJzy* ?i!$[Jd'Y$BrfRk{sZQeō3dY36zsWIZ 425cVC#;mJ\#@)zv`uM/JDaYѵ_8arN\_cjq a2мQAQ%^20(۩4a~1ΨhklܪlSO'D)KwSMM>MDgߛTFŽ+ ~I B (!)NN3MRbZqט r x_JnĦ2JqZ!-' tΛKi *Hi3ĥĐTrj^y<BU o/>z0}L!9뭶Jͱhmy)@l(.=Tbt{V=ќ71ı;SjZG_]15n4KW援 t+IeC>sjo-C$x63~fR]jFe)ô 08:U_2cƝ5qm%ּ5~mBKթ-uPg[K8 BKsZ37,*C_v62bX Zw H#@EQ)J($f. > kID8AwU}c MKt)*5DέĬ$CI/K. +MћtMQ 9*F8ޏezJ撂UUP{N6nxΥ.|f%!y7Ohmy_ U1k)hiaIބ7e6ybG=)љBH#JF☦K#@K~ ྲྀZʔ1S}bpm[%<¡jU׳\m"j&ZFMZJ@O 0U3jW,I+AC;[FZ*[ ^$rX}ۯ|4w歃SOsíq}ԣ&EצǶ>Az-e1LCԥYAYS q-)[![R7W*Ymc_NSdt5{@ &RtĹIXf8+&ݧ<ڛ/\CRҾѰwT1bd+֋џYv&Klҍ1]exjlA+>GjdYu O@;R0vOT.Ep»#`W):uO.81+N:5jqln0}w|qOz#$66|0+Fݠ6AF(,*Kmj_EƓpe=II7Ѣ) ̖JTG~*c. 8gE}ͩ3Mo7G'P:) B`Aލlc 7I^k$'Xgmv0yfX)+@;P&-*FVq[;g?,F 3Iau͟#d8D[Cͩcn*H8IDi6yrr𠱝¹}Oj%#'ʍEKR˷EI|[޷^)Im$}eufQԇCOZT@,2Ҿg]xN@Y0qR?z El] ԉpz=NʐFy~U'Gp&#=Z7JI:[m\eHxn6m=Meϗ L!8$l31ԑ>__ʾ1zk⏝d k>+I9=]Hj;g)R4¨qzAS}p@iKd*=F9AU%֣(t*7vmwq0 RE:BaNGB'j|$1ПeKT;d3 L~log )v4f)D%h5;>г"P^G3Z~j++'vs_p:)[PCc$k{# HB>*ia{V/2H%{nْ>L Y]NR}ұP׎1qg J%"oig{ TKiJz%A&]O–_`1LNy&p^D9޴,֙e};b\$#6u <1i{YjRF>R¼Tpq+:W{+;g[q@FMw8 |zq!ԘF~L5ABLbýJOa5Lb\CmQضPz:?'4 Ey6~:Bz'E#gԞ)O3Fe,M/L7ZU#jj4,9;Z]S+/]5ڹAuy)`ɱ{X9!G ILp]Q;۶h4> n@lIpE su'fM#lkvPvKE)HcT:򒩍jUnJpGuA!5{3c]-iϝ9:ZXxWw-$88YHV䧽܇*]d4#W(\rBhfՊ#ے:fAK~U=J&ޗB 'Vp(D@s|l1}''EAaq&Т5YeóQ#`K$!|u-5ۍm&8ŖeӐ;_xQႜlͬȱi *1pa-xbam pE0bݖ\/Dhq[Ia{1*,EY{{J9x<#~PT$ 苲65`I˃^%|f![y)FiFѠ>TT* m ]:clqIqZIr//U[Ljdʝ{QhTly:VQ/줌$99c'8HqKqhl\d+562{+j͠2 jIjcdIShx Lb0j,|MY[d*1\>ȶ-26MIT$$ 7}%>:)f^S2BO1[5`HmXЙr쒦JF4mRTr浠$TIٜ[yKewLn)íWѝGH攒ޏ{"wEiK-PP+D22EG|K/'F1q% nK͹n\)#d)nˋCQS'9DhoIJB`u@PR}Tav[)yhvRCiY(`;˱I‰V_+R#%|'"1 Kf*X_ʵa2gR$`glf.Iq5c_N13-85Ō4 hޫ|U)m!Hf؍YlsM,TR:m\O20 SgAk*2l!:yӗ $m &lyPqj$l@<0:"yѝF.E6) Y:8$|K*e;dSh7=\162WEK;.ݴ̌Q8^j@\2;*C5ON;d]+^F9|ssiGgj#D=/9Τzts$Ԕv‡i[P2ݦzVCo) xF{ʒ5mwÆ.X< 8IyL\H츨a b-֨IyiJ kY;M}7,d< in1^YXcBuq.:HQS'(d&<1㲧wm*3j6*GWCdlymWcck[5dzS+TYyp4O6326t˝84jC἖zx= =i9f'.xo%_#\杝E#ܠ/cM 8?opdf&،Y$682/!:R%Hr-Kp|RlKDFORIf byu >1} `]EiA06j8-{tς@ST m-O0Hۚ}Hf/uQLjhӴᒮ2tXd,~)mw$rHxCc3QVau8BA#z0}o\{+/@Aw8P) tb]T6f`=:}>5S+L3*=4YRXYIŒ,WK}O޴*Dyr)St,GR<_S?UΔnhZ4mk[:Ou4sY%Lhmr𥶸V: Z ]lɀpRRUw=Ƒ܋\8F}wh?s,fnYkir)?:'j\و_e\$Y]kzc.s ƇbA&I>4P;и?79J9yRCR%/xD²hjM /B=?|m$WR4 #9#z݇s5.6hqZYAڅ|(أEJZH)YN3VQC̆}'MKCYTG2Z ecђ2jL=8JG²M-'N;yV\۫c5#Wo;O65 4Qp3~0vޜb#OO=(y:qd\#t6V 8=*QPGJ6 ˥Eh% $ v6( qc84;{d+kd4M mND u lجb<Ʒ!Jm(8J >ujBIH.HDE,$p>tJ6)lV.[}j irc9t~rJ}el] NeL;zp >#띚MGk_`j^~LegKOOo rk6ml#6tox% ͧ+y'dΎY /VPhV&u\Dy]$ !yHVzy[LBjIB%'vG-g-Kk.O̻ ''sTR.<59{[>;5c=!岤 @z˖[PXղ^՚}`D^HXTܓ]3BF|>E_E)DwZPl dɶΕYi@N SDJv܌oq 2o,q/cjOl NQRŸBڸounBUʮL9b+h/Jo}} ?:–>\ ɣQo 4>ϐH%DT._|*${$u4. hu=Hxʟa5峞F ISbOGq=SsȾ4앃oSx:FikSDJ t|Peؤ&gh˺O\ qŲPf]--3K&ߞ oDrC双VǙe4R\16\RJ~F%Q\)+n^|+^s[Re2 *lxo䲑$"rn7DT-'z D1Nn<+D|? ^t3 ZY?$Ńz1{)R~u{Mt-A9С/h&:{JeC`QW2fk]R_JI8?Ɂ2K'#~djh*O])2cY irF[`I4 N}A[M *R1WMNMNe$`s5v!|ӫW!?[ĝ tRTZyI_@ARdn,9}sCUA'F2ME[#qED!N})Nrv)rnDe,y(r\9@pi=NARI{Oy,5*E>$^!TYkd.%Ѷy KqY|Dm6cNBZmRױQk7qI񣡂[0~xu 癦`|$E3T Is#%@|>Pz>I-ko9tN3֘1H-|<!Q rȤ%Ad")VۧJ;FWkLs\Ըe$ A֠vhPU&L.|l> $|9 ֍N$6c|*#~掱=t3C NF;<z Ml8bYok*td )MQr* \AoȠ_tASgqE`RXjk|wP Qxj>ҚY` Oh mhT&[.mom.\H5M#Q5f~zL@ Fux#\uk2IUKȜ%ψmʲ3,hin-턯8ktÔ2CVQK|kNYT{'ݹN}1DD%]&ҏ]$2$[nI JphLro~[ SW@oDK(yڇPMȏZW褹z6cko@l "JΌ2()꛻ijXW*ܿ*%ٳIgXǶ~ r.z|/`̘mwk5ם87Ƚt9 U03]}Z3S;+yQqWS-JvsdW$FwܒJJsqBˈ(aK+;[QOw":)-,9 v˻Na9ڒ7C;%=ES\"u %a8FgVxuS%@會\6%ٲåCi6IZӒS"#mH{sO^[h\FWdQ, <48*ȢY+-6|٣^6ZS~Rj"+%F9t$OXҽojE RY1dLP%:[+iGW(alhFA;ؘsIyʒjbЧbQTs*X>9iwq 9"fycq$Fq4Tdv*2-Mĕ\]96Fđ!G+l~2D1Hp\dc;-OPB)9fLhQJH lp9w mMYZ,1`$eL6^v~Z㰢ܙMJ!7'P;RzbÌ=},҉'0N(,…G{ w;z5,)4-I)>bT|G2aς#܂ v9?83w{(oEk <$0QixkѬ8/*Ui>.7/A S./=d#F Oq_u*,-^Ͱ#'lOY~i{Wԥ sBdz4/OqvnYl† ZpIД| Zŝ?!ITfzځas]i)HO)+){$C^X2T+{E"JV.RH(gAn3zȆAMo(raGK/])SJqvO.3նRVr,p߸! I'cKٗ tϚEl+r>.qjSC6DM0I<¢eR4[mﲶd㔫QU ;by__erP[L:MaifVR fmYZ4A{{4.*\ sP;2b2#-7m }"\++9/% [^y(.RrTY>E3;RBG1V$Ȝ^Fdl1J}pLI%QYČV_,gz;Z.2CMgbVv=,_@CљZO[x:gO%ip& 88vRUMYbgOn41-c(0,-YjBҧx[e^Y"xa=R)n|ݚLB$v䪲-F="M2€OlQ.Sk=7!\t'!;S3N!^@ QU&TtFHJG0ZlVi,4󜠏\~GBBy@ T>]4'?4j@0>JFب2(dIބrd^0Og#~(T܉u~:>{G'<,ƤL쭧2Iv0׵6@5h(O"+»񮞎J/% >QPصĽFӾl%X8WWmRRPS*?\KRha$Cu<'!O]nO2ءj3;aTpE*_:-OTl)%#vo&*')ȿo ["[JʘNƙ+LqIUjխ觲1#Zp a^A›9jQʶm.yP$m&XрR6K斱9=yGsU9(،1sȢ•M;m\~uܔ;S÷#ޙŶ(@$ߥh/~5pfm *m$Dɠr_S3PAiRYIvRթ&WtvCRpeDtMܒlxyqԋ,]9G'#6'㲎< fѲTLns(i> ]Hk璵!׵`!e&H! SNTiĖ_]rӕmU9ձrcbGF-4^g-!ඞVjKfؐTz#cֲҥ%C~J8n 9,Du(u*Mdzvie,7 PGF{4aq hjdhHIɍ!LP->zŠ3J')IH9e6%*"Lpb#!q;()Bi[{͡~ʓh E/F4u(ϑ^F b/#:wJŽ]دiF~)ڏ]5m9_r6G-O~bcs^-,Rt^˱;Pޢʔۉ(qޟdѯ& 7I#Jqn(ŠNRfG)Q<>)j$Aheq7FzlN<{XJRAT-57FAq1P=bώiKlhsF7ȧ=nz>mA>曆Gy@)vsΞuU%"NipkJ*jK=?8JN g\gJl(O'+‹T.OOxRl;֯)m^TcE9*5&{lV^Ӿ2E2*_b[_BEp1ŵQ)ۚ!㌙xl̄C)ƯOK \ m--'V~ob>.Pϴ#-7[SNȣYftl/[~נSBsQ&*JK CwAsS4g{%-m5KH;(v^8UJx9f(qWUJnK}ldm >ƖgpJH"C0qsH?7pABH*)z١:L(.ߣQU^)fgk{pXS/!\á4ccVT}ܲӅ[v4#p!pQSGj\.iw #D]N[$aܡH#/$-po,^TC*RUNT`V=ⓟ4Ll~=.\]a$૔QK[^.Jy Q58mY4ֲh}a ŴgH@km{gsv3R$mv}sQ26 M 6/J5El-? ikEbx=;Fbs!iڔ|()|.7?&2GyNۚ&ImFØ]vHL´hZa{.C* ֹjSvpqRlYՓs@JMHL4i|(!fP$6׹&XƸM=,N防¹/[P/F'? g..w6]}{H"Fe$Ag Ϲ,JJ^dvVIFj'ɵi)P腯8O]hW]LAm$83B F4> rE-kWNQDF8q&.#wtf y.DTM:]t7 {TF4bסr6K"cgl?\vDCѮ]ЕBe%.rQ|xmᅰgY[eˍZeeUJ98 Bۗ=7:X}Eԏ3ÎID93w>U(<)>$- yiۯ88Pl][HR>%$mJx+~ĖԮslR|dT6smHVN}mKbP{(\=0 DCZVۦ4iE5= HK@ĤU~xpc$~Q, x+sƒbwVeg%Vl*[@wDwNyIxU2TV@C䱃\o>#4I;MSt-9J@=HÒBGmw5,^R69,v.HS'@q'̦Rs} ᤏ)5"M t<%)i]& P;OBOBXȆ=+p')Wb/Ք^i#4^=K հ5cx Yb }i $o[}0k5BbVnUp"R JkSXnAJRgTRE헲@.,6Rzy7 }0tSm) yCa)>I5cBeۂLYqBAVOYPi } O%XhqңL~|o)'Zi>>W/CXڇeZHJsH,/erSVHC8$f"E-@79 :dke&s}SI JB*(-1a½IT{T9GvRL*M!垎'ݠs]. CEl#RjQo4@8l"RQG>i!<`Gm㜛˽-LbԴLWB_I0s@kWqz~WQ3KxiYԊY_,r^?V]n[;n-h*SOSF>J:KQ"Cl%o?Rɑez3ZncIFFg}Sn%NޘM:6^ԸHBrڹOƹ3$ SW0i쥂3թF}x R)DUd* ])ځƖ~1jDNQh&o)XW( #`uީAoJ[ >@"Hn #vTt UY"N+ ):[((`t4bGQV5X$ GBjn2JiMXO dakqJFJJRQLT@˭49޴FG?.+_~&/F+ -r͖yF-~>,S¾`]Yuk I 8~׍)M٢8683Oo*cVGJ'|V<\E!_Ll;7`Gն ?ZLkG)+՜ʲ<뼶sSipt.'ٛ!v%ؼRnu:MK9֍U핇)Mm]Ɓ{\BJN 8'ɇ$'"8F+mᴃ鎕r(I؟^Gi; FɊ"i'ťiR6^8 koڤEʖ:dw#Ͷ-FP,9(FG;!ʝܬmm#8N:RT4DcB; kwG۴%A)N3һZi[zktY+{m[ɋF5Cg?5`yCsvLZn> H %[@2#k JKDd$v.\(J_j`э:3ڂCC8yᰡo"ᅕVl9/FQMp8ȷ^lج\c|2Rt]yeHwVʒQŹ1sHUҜ) 9 ˄&÷>Spyb塒O عOZ;4-_2.є]-21BD?Q]rUضl$ضxyHT/ h_Zc %Iq)#&XQ}5+2:ԊGB̘Q"[t IAay'46Z &$qP9&Iu7AI;yImјRRq v^b26,M`: 9u%cp@삹ˡ[D$8yU"-߭Yr.@`\Gq!mFԅY NW@ns%f1{"ow<b%ObWq cŕK~&M>R'$v(rgLu ҩ.9~O uhJ,F>Ž^qr~4i ܌sExE.SKdUD6fÉ]vqJPD|cI?bV™RM[~WoEJ;rP%p=J7{%|'{mQD{>[R|1|B<2Uqsù%7 ŪO,_JP99JxGyvdx~6sQaL?̤|F$ J Кb3-]|4յLQv)Rn\)wKxbD{G"_uӃJKd+M^%@֩te?IIұ'pFFIXpvIT1ƌZw_<6c~\%[ޖq$9)V\. 񸤼1fI IHڢdHOTXVioM>:9 HXs*qF姐p&I$oLAGԷzk I|" Fw@ƠNNǨlbvm sӭ \HZ$.i.6k侕s  E5HKę jsHSˆOYi9R@ Đ:BRzbKTA.zw#Wb2Ẹ̡ QI7l?鸮ML*k?Rԕp 6d>#YˎLcZv$ԧ ;l8]j(p+#99V2h(~v3h j'gb8a?Y@|hŒ[;†~_U|MgbHr*\_ivAM4ƾgW ,V3($GKIZyF;yW.ΞO(τLlIޖ$~HLf*WZ_Aɹ= [6ȏM{!$򧪏a@eRoo0lsTN»p&"zDiIe\MUQMysc B1: cYJ]v5vؙ7ElJFO3B. S֞o g֘6r[jqGph>㬀^!KL5_)ԑ&+t^iH;j($c[Ҷ=EThnL4BJ9Xc&oǕ>Ƙ: b+;$iSOfH__!Tv]v&(%vɠϼ\Uٮ+$IumWE@mEb%Ů\)*&@ݓb]f3 02D%( Z%-%Q 4dLtTYd,UIn1J{mNY~x~JV}RjԈGG] +kIj{Y1(~اFɭ+,Iv$ԉVI0:Pی2&eh@ǸVu cOѬ¿.-^8_z*~O2t*ZyӢ8oWEH7/E Z4e(.*;Z%!O@it%1$P|Khh7 +BPqAA(ZRRJSmi=B ޣ%'ko-C*R/{..\K\&$xvh".#(ҥ61fia婡.58#ؑk4sEPAH=ihJǮ\#!Iq`t':ʤʼ|."984c7"4X.6r*$SI0z6frz )V[VKr(El D阡&_GSs&qEE(o7%{! v2j)p_@4yTևޚ)LtbRAj-^>1a^/LByیTS6/_eh[˽3.Xͥ滃 ;rGU|bp-5ޜ+"G.O:Mh7Σg;o@1Yb%$S z H0p>45HX$[rH4nW{JƉ#4@f<EhzR2JCJX%YǻY7іn+O(fl%?,>;Nv\/:G\Mady~#*$:LϦ}2<Ӯ+H[j͑rpȂqٗEZLbҥ+-]y¬}{GK.k:Rr9R>/n=:Aj#8@jSfEt5l&]3{cK -^7=:eSҒޡ0@'QQJwQ8iptZ%LM?[E>98?|>MMuJBR+;G/T|TDk>=+eA\jŨnFlhm"ziN+#Ӣ]̮ ,x,:H=Mh1evt:IH R܄Fhi!go#8Oehka8-D PR HO\}6mGd%L<yMd\ak F}Jdt4(QP22 aEܶ" 0eF{Z&2)16PC c?^u =@<C,$ұ4EcRDy–mI궴a6%Oy+>J䍓=0ɪq3OO"ZmR.ѦU(y. VCE#+N2 {^4^m9~=*% %i46)N6Kg6bcyjHNŠ6#O'&K,:o2^|"^i{ 87 ڕa )9%E3C(:CֻR`4hܙhs*l\!x#fͩ 8Ͼ*1n2;Sj"0EEjC@o*n^Ҳ65(:e%ACSWlIЖ/)7? =_km-.?E'ʺ5f.`\dy, }|RL65͸m zF 9v?[֊C=.j"dGwaE4Өp4n`L(ލퟢ'lb&O!!\uM8'ȿ>+j/ m^K(N /L rRC?ț#,2YBΟ"/NK}˖Inҏh/.vGjB\jHS B\Q;, +M6O0Q{GN3R_ȐJۃsmA守5v³SiV2D,tKqcލqcS + SIR8IN7x- Hs>4;X|#ߒeưUE7Q%V3 Q-&IvOZBor'ڡ)@G'Mem \2VP)SA/36A{HU-cGm-ԭ`}Adp2}AsLSLIխ{Mj&,wN3hXh=aAEPDwh&gl $3(R[JCl% ]ԩ𒑀)U-Ժ mk^EQ5[IvX)?{^vr:B^9"LOn5.[iĨuU>Vb<<-d[2ʱ&M0)T5V’]d3q1(MUArBM,2TqF"j KAP8H4-ֺчߺR: @C7~P-}_>an'c-`!i KCa~(iY`C#ds} &uE* .!8"ƭ~l26)3ZSe'49!T?N+<܃ڶAR9ӕb2LD1 ( p~UD Ng44 NSMeTcI-''gV5b9wFܛFXI\΄pIN7(w;9͖D m@:ͅ?uBҵz*EnHHVnKh%!!$1.I~ b.puiwZVMfIsV*~̼HJ%ѓtd֪#IÖRADoIIWUb38Rtڅ̵;mJmXNJ`] uwIlHRReٺ5đ|GZ-2N-ˬ,}Q7m- i| wL\$;Z.- r3)-LqC24g| Oj>HE^RD?WtE \.m)\q>TEUYĚ[褉n+GHI gC2 O[b ӎHrPqB #JimO`qE¸}/×c_Gˇ \N2>cQ̊ jHCȈu5g^sӵ)|86-d a$bCy9{L`ԑP^H+Qj,tg$O/hyNJ>,=ʳ[#mJHicj㤗`|#f,a iJ/' { Vб:`P Hߨ{U cm- |~8B-( aKZFk4X-"<[,T6 d ~`Wِ?|kvO|m>DzP6YN,A >0S B@=)]^E"u(tڦ5f5M2 wm;s/֢-=O M?JI,(|3,"v| &=)X0. v5BEJ2F :0K橠#P1 jjv3֭$]3ʏȘ=(_zةbC?r|$듧= m-RO*a'asHd)G̷,ڐ+EcjN(Ѻ֖2Za-WߔR"FB~h(G+ALUͱP^ˉ \O~U i2a`8|)3E<ZpjȎo,oOaӡQ`22Ғ; oBZHJƚ7rKEgsqB29dwq$})OBǧt{D͍f#D50}k?= 2Nz1HxҲ-Rψ .(fl[Y0Sw/h2X %mD1/ `)\!Ɩ{wB/jAIJUط-τ&د4wBF368yZAqO,bQŶcIS.4L^&D2@=&9ILTQ0i"N.M0Cq |>Z,+7[6!Y#Ds2nJ2{e QB TYHܣ+B^JUSA)L:y$'cAVg8t$IaOظy3dyZUL[A ~4{"p8R9%퐝lrQx,YV͞n'˜XqteGmSiސ>K ԷJkxVf'] w?o} s4Ś"ޞDV8j.A{k޶c٥P_V}OY -GRsW d<ۍLa X`jZ"hiut(G5jqdB0BsW@|BHEcNE+O-Hơ |AQinCPoLkW"S!8_>w͡/X:_e]z#sc} {X#4IK QPl@R10 U޶IڜX@_^ﺐ`VG<޺+X4սm8TO~Zeni918r=_P9ev0;PF96a2@Pkg`0hN@L4֑jd=|QH/jszIk[Sx=rW.]'AX&4@H \N~H`R kEKKYN^FHT,CS/XwuӀ|7 cdt8[HJapg1uC!&{V>='d-g`UemV& NEm !DUH6.\%YZRH٢qW}O~p\t.IyN;oXMП_ *O掦@(B?wxHcm9)^Sƚ撵•6m$ 5-xMChb.:Mc9os%\NπDL}-u)niQh6DdT@Mر$ur܃~yfa]jRsޤTr1'fG nnU^%гh`F,rY>@bc#M_[,J>c#dO laBAw,jO)i=czBTlT6Z2::$x1@R ٜ`r1Yr1w-?S\D'q/)#ۛtу/brJ|CFrDNu :M%ے$49T+ζg/SIn@3gl t̐rOZ8 R^,UEeΗBp:iY*q}fBTPItRJ}+|!Yڐ5$"ܧ4M䀌-ŕ#ICuˑT )5*6 ܻG G[e0ܼXM1n<*Ob $׺T2ڊ*Q$FL$ ;|*-OBvw;&tz8fmJ~w^He!5 KtzI*B'tKbcd0iIqF=:^).y'5{\5_(FGEnԐj@Q+8' ʘ-I:9vb%~t5T#9: q朒}NOA]s·jCԆkOҐڍ d_#*;y3@ݍF,P/OFjvh%+46< :~s=Jsސ]bku%*nH&=PN:tŞ=-ŃRFsI,J=2c2ؚo|@NGP}c){mCb؄6J>9(mFHp<'bi/9Pj?̥(./D/[YjjAIB񰼉ls/*=ކkkFط8RV"zջaR;qrh-cj*ɱ10sؘ,HME=0SMЉAn&"Хdm{cTv}>$E8M{9ld֊4 poK3Bq|l$y$f9 ~8C|Bpa@wRNh ͣ0/MF):?"2 <}9-8ːPd$FsQ&낾eD8{) gQ5#rf9qʀNsSwڜ(iհGa@0_xge!g4uA,j/ykQ KAr U|늤-H9YV;}jÞm:RUODg5w1[XVjm@÷rbFʡ ?AZ~SnVLp *C`U\=K^Vu~aV'qS3+vFN,]k/;e˜XSq|6Ai$cQeE< Pù1{Q9rȀxWh>c"FQۭ"kP?j`oܵU'g>^prd}eĥZG&[0+eƹyV`hrG`{"%Dֆ콭%fCb[k@EJ@a:jQwYq$x)CScώ\h\y 5Zzih%ui"]Դէf̲izdC9 OP Z!Hx4C;t.WB7f*ǙDs%'5V94 = v*l,]hvub- qrRqpKcF.*q޴,Qb0Zq;r[P}eq$qrDk]A>4,@x!I /eD"WmW[ZYQ,UG=NbF'#ksQ͉cAhqKf/̹XIAB0fcM(Nءl$LޅFFH-Gʬn@2%sM[LI%Vi鬙"Ѯ2QnȎT4k>.70֞$y(f[Y!\;]RyT$d $~(Ȭ86F*!UjǒqPNoPQǛ6s^2]T%,'@d5K$XVl'JI<2DIJ!Qo@8It-cS[䜗ս&1#Yی;Ьid7ҙ#%-C0cSP4weGLB*q`,ɫ̆ධO#B !N AyF}F[a%I\U vY$ƹscH5_̯N̒˞w*I-_A۬3 ^ )};_!H/ƵRQ9<$%>Sj&8!R9Pnx&=KdU4֞1ҋj_#^IX!1R‰VI Jl2ܺ>TՖBgh7gGGn>CvC |!]=>y91T9kRk+|[{!# h,1y)@4{p"-JaKrlexGZj  T '|Q'|T a6_."hKʹT\~dDӟ:ol;ЎL5;b0cj/=@9^61P*3,ZA{J9TҳMl- *9 fNYĎCUOg^)vӪ3s TdK1o1@5[kt]3 jHV7<Zd:7ȧG% =[m;r.Ni.=8֘Nm;OiluBg+iHVfeb}%-֣ u/Yz;ˉ3HV;tAd&:$ 2<<4s$jߢ}iW)0ʵcT-WEHi_]7hkE Y4 B2Aj\H^-Ғ:N0j0 IM`I &MySoIfč*NI QL?M&y-9jMHyƭ-¹WFޖcbҎd/8 Ŵ^MT0B^!j^Jɉpage'JxѢ91vTH ?y^2cA@H6x6MU·2OAډebs8zۍQSVA/Bƪ)hFϑ3Jiy٭ϔb\:܊KCR]N2< @h)a )AS@բj'5`rח;Di}77MLG[kF-ݟ/=jJ xNYF&F<l%ݺeDyQ&Zu=B΢ qW؈9#QJS=_ h <I%VdXJzV[tjھ`iɱHr,|-"b+^x[.ZOD Xմ%xle¸aL4ՙ}edG|VThͲgsNnLFH҉n)uNi&F@W֗0GPr(E%%5 /sgZ CxdPN Œ,=P2ʗΕ(1ho(W1҆+LeJi6~ǭS #nulL|0^N tr2Ą)*u#LY@|F bʽWDi;e֓;ѬT 뾑]1#9Y#%@:@|d)įIfn/ZY\AS8[>G%f*ds#ONh\7DW8G([bYKykE. ƺ-D'ە oZϗ=7BZ'vԕ*QiR~Z|^ByvYt֎s GtoUhgry:F*Z#55ZRE䑛wV}%-@L IxΩ*E+"c6#3($tj'R`uԨu-(MHQ"1'4jQ[%4ZQ/w*s)x= J/cajq W5d7sJR쳚 3peFHn6qhF6R߰0uHKؾ,[,m$bsBC724߱DԚM3j8*֐ ? L .|YvE]8 HBO+=VFͯC>/3ۏsH$k#o ~t$eΨMjw')}? 쭏S.\|R<ɥ#/;^v\g}7̾L$1qT6IT$a>UTUd1/zF- ۙ 5ov)d$!s̎xgqI/s)T~c[b˜2l5 d>10 0@A2NiQNFA i% OUUad- 3zjwV `[8};@ˑuJLK너A-,AKbIG΋>hM7Q[ٺ4ޱdѩtu1~!8$_'ODj*cs~uϞq:Зejir]e@)*ia@Gt(,lIE qiN:Ik늍!1Fգ#0WI 'ZEa/ S-2uuPvA1 bHBӤ F- wS)Y:K8''6f6–Ԡ@څ-ͮ},%isn[ęk<#rI jb/XuԇTg8=;5jZjZK(u)dRD>=jð-xzR>3L(榈|1Ϟ7$f .rC֢e~HCBZf*YQ>[r)ً_YZ"m+d nzQiAZyJsRq)1nxrrVQ2˜'J=h^x2+EQ8ʾ4Օ6%;A8ΘzdPڸ+9ɧ,C3de!Mu<܊ 6iziCO\T %>HZK},! SG]܏Jy[4GM;\ZJ;w6iKAJI%Г  )}vA3Km]- lBϖR.._E-=7I IAJg?z*{Re[*loƺf^Z+!FP(Zo !W f6 Ōf\W2Y0j8;'^v$x ]e*sP+ (+IR.sm =6(#ެ;ZFj}c*ɮn$tGl^)LFC;`PYDyRyG]S:eua.B6sh;6Idr#YJt?*.E<@4C/y|) > \t=oDQ- srd񚚲OEyfn5 ݛ.&277f4 }ӊb6RGQvHڔԽ r5nn(K2@RehϾWHfY }(*0x\1@o0j Ng'FjQ92u*Zp //T|֯iWdp_HԆ/b, Zh$ r'4VK!a!DvnQΌ.|} Drc .9f^Fm髍^*LFw[lw-NQ#Fi-CVv8̔(u~̓Bũ~UIN$ -hj'jmm؃@1nK/z;C =ˑ{ [x܀{h^8fIb%EOj(fw/DQH/lIHI} S69εR^Gu QOƫ򠍇[TN6[#pzP0]6*#m 5rTq27tKQ 8T2`3W{"b<+2L>l`Â2;YZfu|a9=MkrE6j;''`m 5~i˔b,ԲQ{#=3Tޢp"l-DxmM.FE}x|m)6{VOQLthxE K9Օ::Ǔ&,L%ic*p@T,0VMФaȨ 0EPI8 J·=Nil4HI*#Uw#sv%HzKjOk1sv*S>6t@Itl6,d]aTk`BQ.K/$ բH f@ j&CS]*i87,⥕i9"٩Ĥ``}­XȲVW 'oƢ0h8FADSf `*rYKSK6W"nIڇ"s0*뒷|et4c<E~[f?}KZޯTbSWvMEq.4GV\r>:BnH3"ovՖX#3^-T2Ĉ|G&y)t^g/dY_.ji֔JcF#IBM;t4TsVd)JLb!faܢJIp2=RĨM Κ䅤a (oW G2exg2k%cGk9yk QQ,t+SV <,jUv5t p6ڨ}#n~g5Dm<(S<=I\v=-qcFjf6Ru?:5>ΛG:_%"@H%)UrOgaG%I M f*qF"Gs2]Y @ V @S bBj* F^jAz]=M-gi~($%LȎ#FAQ?usrrtVrC'Ok)F9#Qut@ѫ5h]T%Bo*J/>14{n#*Nk>WCd3tGPSK4 13'sG>BӥAl#l8ڗ )6K[ JVƮ9 [Hb[py_a#]r.q+/ngqr)[Ά^|p|ʨ61YmZrUDśyDJ"aA*B{*3JU }U[EgZ8Xo8[$d($B[Hwy+<D>{9*Y*\vy"ļSF:˸\U/. Nh*-xD2#$Tx=S~1Df(Utq3is֬^o<%6+#IYOt=f,&$WMWJ{|iۋ1]N NĹnPZMм}$LP>G<t!JOƆAHۦO &65t>uT]1;а–󺝻i`b#p, ܨ%P8y$n<$4b9ުA$8'qҨb0jFCjӁh_ ѵ EepNBGģs֫}!*k^vޡ H';`U0Ơ$ws$hAP9J1 `95h\@y)ң<:cEGV3xOYS W+#^4y BGl Uy-fʇM0NUASAZ5+$QɖxN]p q>{(΢EHVa!'3Y'O "1k35!=3Jd d|Fuޡd9n]@2ڡ@s+R2&W;p|1ӧzò(ͳ0Ͷpgi6GIPn/jg6'*"@⸿u yD;삍,5 "[yc&&)h)y -ɂ$l:RZv"NRDP0*K@GQl,+)6oC6WE{y՗.+(Z@=hǭ?;d-CpE&X6C4y+I }Mt: e-?^9!*prʤ'"hk]͢U{(bH0R)m:A~HY@WÆhc484*K\g&+$DW>|| JhG~ArRC,PxR%ZHpC#`ȯRh%]B34-4Zh*@UV7Â" m2L8 gRȒ9-F  G85jǹ1 "h4_nYeCYiK@9:fuʷz  9{BRکCvU=Hy*)9 WE,ATw3;}VT/AiG^bJ$6sKxT%r"H2ug! ʔR6!Ξ{ "A(De}'G2 5(qxl P뻂7- [lw"_sD*ϵe~j(bэ]p®Gԅ̥ y-sؼҩ6*N%@[E`+tv4ڭ.,X,9%O_1X佝8Nq MZ*AJ~ɒ6¹pRzsvcIǀX4F:H#z D© E$(.`su!F kY"e_ira :~:u;`me6cMOMჰuCX3> r(GK/ HTkRQ]aqEpz1ˢkKuʳT-H(qДdʥ#QN T|9G $PN AfdT!8Nɨthw(բYkdwD i`TA$vW Ne'|bCٮ3uŊ^u-yWT ݑ'ޛÏF /c6 m ӚiɩvT?2 +˪GF`"C@5r?*8Q'z`p f9B-G4'߻<ńY+$5nmp=pt5{k# Эz(dF(*{BrNFEldItL t'5"KZTڇJn55jMQfösy|MVc3Iڧ6xH)>`TShdp=@Q?#,q^덞;Qy>==t h˥ #(.NsI髸^/PK$;&]7E_ȳPdeU,,[R!̉uYI< EFÊA;|h*aaųeEm._͢/Çf S#&l .|MSč, 0+-7)HT&dF䩕 ޢ/Ÿi1%ƮhXGec4k NBadE@< ncJY<ñ[Ӷɜ(9R4ŕ1> .#Recʦn`ƴ)im{L)BU] DxAG/FQQe8Pe\K~2m.J7TDUǚWyT3fl>*P|gFQ6|ƨFGGRrv(qsL3ϠyFCnD?I]Qڨ}YuʄGrբ<Z3euGNTnsPRur|+/'wm*Yr,wQK,Jq-qٸ6u Y[²FH#Gr ?K42BC@)oM3vVwA( 4xoS);To'#jJB{bdLJI>i7#݈wjm)LonLq߄5 BF>uӆJtnLT_"F 8l(J:N(˘V:P4.mQ+]@^w3N4!#N .[.ߩB]o׭@ Gc"'c jq@oe5DUj$$>TTsRt$ђ <(S*ﱏ ';jIf-a̷fFqdE'|\&r1EY,A>Y0N"@Y*94}`ըF\q(¯^a>4 IćGs, 7di=ic{J0sFGKK!'8 j13bl*MYV*"u4Z5g&\ zx%9!Yp1R52$w.H$JmCdP< Գl6-琒-yqC38 (m9 :֩leH&d:sҟZtYw d巒IsENn'fh(=G: q1@$ԙVP WEp vK1bV6+($薽$Þ j5NRRjX;#=d!%%Y?*- Ƙf[I5[Œ < wJٶa. TJid 5P$}Ee53D+z7e'XwX)=0H>Y%1'Zy$RaYmylUX'ʯx>^qj)) qS6\'yCǍ)<ˌ6l}#oli|{K<7ғ~踴QRkнXOӉ?f =ɺ Nj6&䋣ZpO=w#)֢6H*:y'6yčw+U_'nbʂ{!?e#]85HBčP4db}'U4ȺMĖdM>W?<\T$w@ja*xmDeZlfy/٤[ц[]2jk.49q9<6I).}R^3` 5cyVEŌPq!I;t2!8 41D%(o}#-8$mPMd2mʪ|։pt+4E#eh?*,Q5/"EPo#WfWe7tk-eMG~Sӊ\2pqZJ]܍'%Q&{h!մR^ISj6MڭvXqI"O=5k_jf/'zj=/Ux1 ?u_ )އ>}Pw> }qz29˿Z z&W;K(TygF_w)ӕ?ƿ®>I}=xuzĻ3RZw;vή[s?:B,m8pLSsG}ÍM Q#'.,0`X'[u*g5 lhe!&bcU5Lja8hFY|BkXV]*;RXTbF.C981dYZNsHct>/KZ}h /{ī$3NAO AYk/ڔʔBw(`?/B4I db.,;udCUhz\fqסD-blXq^K|PƬa3nRu[GtD3eǀ i$ \JwpOm(9>U,NQÍh%OPP;!JJ&seTƥF΀J6S $76veɲ*E>T4ᾗiCӰ qB'GFQ % 0VIo:$4(ľ22+$ٳ!*Fwްd(  K|% dǝʾƃ> a):W?>oYUAIURۛ3QQ?EqGO:!{ %ӔPM62aTG\Hx\!$GJD2P#PPE aT䑏woP0#;zZ0RiRL($RXtf1eg!D粍"ي/6HoWL&?% &NZatV\8EUt)7QΒkdW7/*\c%˒+ Lߎ1L->nD"V? 4TZNŖH>p"औ#/MpjoPr(PF12ӤskY[E~+)n4jhh5eϣ*Q;j&ٛu<? Cr:PA&g1d@` V5dr :LyABSĶsy-g HkOO ,"޳H*O|payO ~o:oFHeU%)_ ZEFҔO' vowCNzJlB<%`wUe18CIyQHCֱ3dkɕ6hΤ)T#D QY<%`ZaUz"U%Y4jO-MFNGP-?% DGJpjZ_RR[\#\.Qi/$}dIWTjB5j1)A3=yep~zFAG<%Ṷ2O#BԿL3}d {v^O?|la9M޵'1ңeGS횭\KiSSl~q?GHBSO>K$b&ξi; 76_tBH8K.pR\mH Ԓ :7IEhSL6lB8ʢ3H'seb1˽Eg ncr~\$J0lmOt[<(nܒs]|qGmyHSd;fi56߭J)02GԦ[;s|P[l+*,`/uJcb \TkѲҊTxdH ch+jw%*?ZR|YR-5uz幘r??҄7ȯoFs/I 9֗ph62z$̀) @8) P#:ޏWڎ.P?5눎XiaeHJd<[_x_<+f% RHcE^ڧ['Z;*XRӚ&ne*9"ג'I=KJ#zZam:DĔAw鴟>/:گg90hKƃWW as>;g2G%ϧ϶?T|ST!xCjIw]i N,H.: <@*Ρ*տA;jn/FRaCaҡ =uKuY]Y>yOxP3|V&9_SДW2 #$ -{íBG[CRV%kQ*5^B37:['((eW5yk]5="6M'6gy02JB:! o="=`Xۺ#Uٴ+KmPi)7j{ZhsygzՎ-#`Ano!9GN;fM-Mϼ ?u[ Qm1BO0* G b4o߹YMqPIh.S֑!!h_-n_((ydR ٱRqK5S59pP|T#|"qF* |R,Z*724l&-$0\ OO:SI V[dYF!R[lpi-L9mazұv''i$O s@LWay(ut,T7 qR| Mݭ!xId%;Mձ .2h;"Y,%-? 59 80 ,ϑb^p^cUZ-ǒ}ՠ /*i̵#j'ft.͎je@x#jp˩#7jBܽj )ji! r*m#oDJu% g:(sקnj0p1MշSF@ 8U.+E")Bsnp &3~PRf??b!ߧaP^{M뢸\mw%ǻuh הgTժ-:iyd};ec~en ݟ,oa.q _7`pEzS-[kK΅%X=VxӋ9߈fyBp=GcZQBSdxXs?e6To?)?|95v9&+op:=UV>=eo ޗs,̄|PC!ҡf-z^hLmURV ;.n[Qn'RBhКW4" 5Y~IiʊN=s9ڡk]*?G,1/zoM^-ܨ#w; xŧgfZok蝪KGך.9 ' [O-K+)O1QH蔍TcͲ*Bu'źo=Q?EuXȯ~Ux5/KsiHe(un*kpBՇmvs%re[q\vTu$HVўK,t, GUyҲ:ц7+.eu(Wdd)'5 C@Z~ ]6c@PĂlaR06M ~Te:":Q?ˑXu'4Q$xI22 &ǯ9 NsR){f0nȹ),6l$JOCRB>ɩm:*˭MJ&06>ûR'R7 'U9).P\M1,ͣUanHڢ Z{F 4oƛl}.>ĐE^yFIX}3A= QG:-yo7ɿ244ɹίi̭ mO*jKF":ڝz*Y[Me-jrJ hjˀ)yA^1kK>I}cE*IFSB\& ¨p߮)F+&x}eR}2-u'4wm~|1+f6s}9N@w5GJdw@BKICj rBr*{ ȢH5-1R-G-53O[tY :Fɱ5]ȕfBGcJՕߦ:ӜN:y=|$ET\flC|mF7:C< 6Q҆=l+8sBW՗gI޵U?`YEBO; B!_/:PoRf??b!ߤdb J"EB|zO'AP#O\>ZМғHt+DBQ 2@Җaknſƚc!C͑߶P8տCG1xxmKݭEZ8Sh*° N4MIvN=4gtё5VyWpuvAX|AaF:T 8fiUe~O+ЦyCv5yF> 85 p;zsʝ1 FQ͟OQ..WކOV)1ejFPWHb9_ a L.h!,rCL_pKD.3T!5yN8)*PbG8F+Kcɮ~Irwpll6 |3Ҕ?Ch &B~2 qQl|ꆠcaCe|uD1PBH)m} Fm(KrO~B'ŚHRGF螋42ZW"bF=QZh' \#HiwWRmK N:W3*֨yz%ֵܑ*Reæ55iPR_Y%mU\ەB0RLkq`; 6yE8Ѻ'm5ΦăT4,[GQeex t|fWO_u^ YXm+В9u x:@1':t>62|LbJOThNI1ܸET蓚я&FvO`G]TAemk](*ApAv5 $j,o@i{}hv#x8SGe_yfy`V&h=g⎩o)682@lu2HϤvӍ͚ X_s~wwH\jZu_JmvxKRhpgKO )Cu(`<4GQ3iY9ez.~)hVbY'8$Vlnp;2c#OQPlCgbS2,RV6#$SI.2~TTUsJنrgzFX$NH@>[ p|$J>[Ua[ JҔ13YeiyJ0z\CltvEhc΂F7/vqfzP~E{/K Y6zSZ}^Z6T!TNR!Bv>S.mSV-BzT!Zj7LIȽIv211E *Bj8_zk |#Frn/~SBeԀx8Uh5 _D}7?LWp=:z\Gbq2Rne,q >~T1_qWp"&MؖHch}BΡqGguozT-tv"54d)A !^]/; [cq|P/5uG 2#!8ˏGs G]J9%+z\yv1f8):, yvGaGB.ca?S(Ӭ8 )*b$cPOpR@^`4Hm/nHI')[W9d~)cig|47Z['(!e'ՖpG/b1M#w öWҦumW҈C}1=8鿦tΔh;U}Ȓ$PA mD֒(XFӌU"6TD#`S5ƁG>})RV6!= [IqM8Vv[Q>;-=jPsYHd~mW$l8K9*od!fn$҉eb^`MڇB*]ݱ%)2h.؄V;Q*M]_b ;/4GśG6; %>|V5!.*'U ] Yײsz ޚ g,'r*ܓFvn1][IUqEe(*3c}IHFNDsJ-G(8lfB EE j)#)H>b`<pœЌMO)<k t) +%N h![$lL#)%;UihӺ+`w=TKS ~^@@oTgSSTQw:ۯc6'R%̫ V1hv9MHɛ H5I04ۧZʒ,ghc#$\{{'ȚSLchi;%RvQcn5&_(tTgH 2J($ɱ$B)PFp4USaRFđC 8%\&(-J5O#AgQos9H98bVYǣl֨tg|y:UB)IxG⏠?3Q9io j$$DײP@(TPq7[u7 uMsc3Dr. eݦyp֎q9)> &6 kCa 6h^GfPU,"LJQ?g ;;*Q(4K 8o=F;ybWF7Ik1ګz3sbhoM#RiHd7w]&DCP|7i n.x@ ((|#VkV$uH&y58]5-@HPeDa-E$W V4[1Q LHSk5FӱE-PTrel@["$ S~ buB<Ä?0S"&D$Q)&/lDv֠yPVݏ,૑/ 88ŗhW V߾ؼ90Rv߭.q|**rb`Oq*tNI0)v8c8i<* knB NWW(IO쫍Pl[3`4;u% drKr0kgG^[ĥyWuV]ˆ߽ZmBZdVղY#:yqޠ,넃4HY#$QX'7]*Ke#;Ұ矣\T6=pu-,jvcVP>uf~&Yvnm<"mp*:[ SLP1o8 oDus06 {а RA3tV NHE79X[-H91]akt) uij`̎BmI'?ȯ{BGoJH8"K91]mW'!-*JTsqB=}f(]zZttO9s$2 !@2s*qP^k Ƒx!-BIAԹuOOXw)OIoDWi[DF>%T+#PiπVWoaPp{A8[3)mMl`xhRPC4}APzrQ IqTEx~KۆrgY'ᅭبC[>[(R6\11 ^eGZ0@y'X\Ӌz7ϯZO"hkm(ʴ&>wRR}:[ςWGGM#.iwm:|]SBUJBQϕBյ}I鏩ZtZ-9 s|rnintTOQP)Cx8zFĻ$C!%%`a#Bボ$VG"[Sb7$-##!!Yy8B QJӽؓcM( VH 5#̧aB)WAʨQu FtPL#X*TF wm0R5|+FYR 2mzVeHkƾp,1R -vV(OA»^ ~+D-Lp#gֺwb;9J)ID:gBKٕj\`ufEn-Zs$?EP4?F"-D'xn@6G`1ErB!2[!vۥO%fh>#sһ*>+J-nb s14#}C i0L4[*+lYD9qWl?$V"j탲 mF_b0?UDԶDhkTBkBm[n&#H\VRiNj&n 6R"+fF%RZEs} @:&ظ8!F2(XD &(jtP8A2vFDgiΣMqM%]#Ղfޫgo^͞kI|Cp?MB 8u»C-UhHzj IZvy #9xo2"Gy>9W!\jZN(' g}6|k7ipVgoVhXl[oJD;su,eg$E#9jlI|jR+ H'97ғ3_G<kmkTk[֚pʩ)BA?T:CǾ*i+s5I BVVr>Qǻ$ Jrk [?^;-Qv)?(OMBO5QBDǤy gi?/goM,F(Xh/ST Q"@wOƨ}BҴZ3K}B`N:P01涤+ yriδ_ep bFA6J&UeiOA6>Ry⊐6 4>;꒢1J|tfU_B83Di2;bm:Ȑv":@2ʝ$*5Pe ,4GMS$Z E|%^hV(G HGuIN=;nvX~!YI.0l1 E\ЮAqR3KsC# JxȘ;U) $i wmOrqוFDsFj+m|FiҲQA0V~4R3Jw'봅oЊ?|8?U8Ua,ۿ6ҏ¦_XP_Ƃ~ %dlNRV Зp['A ciYϙrh}M[BYWVڑv@̈́˕T[p(H=Y.%GYQFS>yGȭ*?nCiZZYi Yڣx}vV#4ԀJrTot +ħjz1ڼ7c Ce-`s;dԢ?*a嶤FvE[%4TĘ )ٽ&(~otȯ*o-#8oZh@ZLu8zh\%N7Zک?kڶdYY<`8p-eeHvPד̰zք9mqҌɪdC.K-PCDzj;ajW$蟡Gٜ#k&y*~n9I=|똹;~!νM]QFrOj),cXZJfJP\BSj-/l.6ڴc:_dS~4^wYYƿEX<=GRYF%rODR)TO7=Ա}ATӷ; \Uӫe J#8NN|j8b2o$F/h`IE[.4Tv˶;>W#zMRGd?^Φ??7/od[ʷ6bȊ߆QPHHA+o-_G~zZmZsUoY ZGiƖRz>} q{=>M.8p+?<[z#No\kmIsCl,y9Fp0:dg\E/yNKmR'@%wX)ZV>f=9V>|1\R#[n޳ #böD~f FCiHJS:r+'%WT8EŮ(7'.pXhmcl9+S G.~)(],8u89{8Kvƿ_K㶻Ѯ|7"͙!'WBM|35|`5/Ed&geCe5UZNA>nC()J[5'hC6E66Yxݵt6%:Ӊ mcy)AݕU,v,.W9=eKI+B7i_5E 5%oh_;97E;!UVJί9W! <>E~&3Rh1~f6kX2,_Bo!`̄);4/>mm:ZKE}+(dsdNI49;TZ,} k6qqy2>5P_'CXe,j᝾4zSVQ$p9#9;2?1W<"MzW@F3/'M2zMG4Ye`?Sg,pzSMZl2ُif$\%ђ9J?TG cv.2ؑE?̢zg'ng7O/0}ZR}|_CY̻n1 SYdI.?Wg_,ԯLKr?#mW__K"lV(o Py-u!ڦAcÁCG^#?D?&t$0U ̤5J8}G` uJSns.Mu 1_ %nx)R(pĊDyq!G%PFA= 4Χe9E* )9v'aPr/@ĭF6\gtxg*l !i)3얜%׭W&!Gܥ`vF^;SRNb貭ץ4y@eh21&=g[m(eiC ZayTNX lӰ}2+Km3-ў|Ÿ#R(SƘ9zLyD`OW6%*AU+|qdS"^#" S#`zt BJ{J] OriBj2HSP7"X\=H&[79ƊGFnkvj!eddssFh)>V9ې\AXͤ{HZsl4Fr[NWC5i2.O?}#.mOذ28NZNW62*3c,ڰ6l3JtEhfNh잉V{9Ee%o>;Tmwz/GۭhZ t~sֹ9lzxlZZR`f)c'7dzy?Ŝt0~WDuZNycP^;CҊרICW.]P]I.U7U5aFN=zt R.ۼD9~'B}GIڄR@@./:ⳬIsfqQ><3gCjfb:\A9c$Z @}B/zש[o6ksĜicȡ@T!צx_84۬ОBouJeԯ'$d);g8)cq)nCsEY{aM-菥b|*ⶤ' 5}ơm zOwƙ@v(?#]|/|y,O^cjL.2ޢBei@w1}sY3k'<փ!+H1۹wC=L>dHj5xR3~v^|*/KQŒ /p?i-E-ah9rS6~U )J씚t=[ ΰU ڵEz!.IwR(Arʉ铀78qŻAzL bB)'b><8=\Vy683:_W,ǞrP6m!)W"0]t޽BjHjkZpkǫ nSQ2T,#WP=:PoZf/CCxLu>#$ۋ6G%U{ I)?ơN<g~!=۳kT2I'Gފ&c >`_ZCw+|[ylГB ŕvQh!NO2=Rr;P<k/ݴn+E|줏u$Q%hW'WW'?W-m&2\!ugW;ǘ޶e$(^6N#-8Y4O"6=aa.y &gc>x54̶ͫ!쑾k .7 An(RӸEpW 2!k5RMcA6׼3QoLQ>`mVM<=O:A!_Sl@Y7? X1$=J MgDuH 2SZh,cTgLHU{TG !ҡ6n@׆V\J.;BSIi+?id*8CЭwwPi : )mD ?Z6ާKnv1m@BR{x?3}WiJ׬b3ΰ#)|6lQt2ENH:_8lގ ?5Al$1nM5hFPu%LG/#ֽeO3zjԨ%2PBAd cg;opO ^&\9|yr&6UJH<xgbڤx2;3/@ßC5SB7;* Op׀'fWNynnڴViw;2Mą}.(B=e 8wpͶ'S!JAYɹ̨BVppRvLJt{Wg@X5u6bJ[BJO BξO$:xX2USmT7oIѳ;P\j}ʕ-yqwCG]_6~QP]q99mrK285qM[+57'$f24tBukWΔ쌒R:))\еE.N%G_#Ey׀pEB/ex*5m&E5) ZֆPqBACڡ&66Y~[I qO1c'f>˩JLݢWY*Hq<ǫznx\8q>|O-4 sF:y\pyxv6ff, ffqt. J8Vɛ%s%CD-" n6Jy0*S)zC͟RXuQe=C[_ u Fҗ]U"rqTi%JwN1:FiKTpc4ʓ.tmRur+avu9i0G^r=*٧ ?.`J*Kܳů!ZqU϶tuPyQ8MjoW>ޅ/@sw*坏CN3#qr 5{֞yuV 4<ӯ6`70~IzvZn[ @n$vD~T!>0Eݶ+mXv('ו8g'gM?~pjԤM/rgWQ8K[$ݸcCaRZ&2 'n-L-)H$ |j;|9>rz{+%6IPRG@Ǻ)²;f:aԊMk'- K^zm] J ^T w=EV<^96Q炵M3hzN􄂥* 2IհCSO uV931d ;Ҫ,b|Ԍ>]K.}P)7oPטR%&E]^!N>^2yf-qr'x~KS^mGU@xYBBJ,dȳIX*IA=Tl7W/s y)B qD59&0"t&uCmS<$U<a['B,Z8ڠVvZД֥.aw5{CE!/F^u@)SoOB3WQ&Su@Se v(6R&RC<;*NlS8/%4䂮A#m_bz [VԦz8h*Whamr!o|V3zL-Nhew"/4xb]>ȌE$x wJ,@WLu"+W tYpdTOs#5V?-b6UBT!䇮OlC~-#QT ʮxuxB="NG?F։}BlwzZi_ܫ??ͨA3ݾ6_f5S>m9U돟B[BBB[65Rov=PUi)J"%!# d3 vr KԞ9n<`N@o-zPRTIa)ku)% l2zT!䟬׏f3kэۇ)H[Hҍ7"cIm&MIۡ=)8^Ćt >JUkR] 58G 9Xг1~I{ҡ}a?pztBe<5']4}_5~HBcz㭳j j \#t"cKM,56 \ ҒlK%|9q B RT2 AZnC)[UᙨJ4h Hʡ/qqAo"C`?!OFq >r'pׇ,akSn\u4JY3ʕ$!-1"j˱H~-ͨ'G(l'W3]'J>PNH\|"H:|ieS ^z%Hގ,V>!.qKhtZDσ% (<諍[f x;+4Q^jv2R:<.ƋE# ,:!thb%>`h(zh)>'*')ޮV56I0>"h9+yCuU}-v# !Ati>Q[@}fXJ7TYkX-|Y<1p!qA(lx"Dw,!hP^LTT4k(ס&013D)afc  57DVuZmĊd%R.m#UWQebu$wڊrh$μa+eaAcmHz3KrFpukƏ wN){kq,maԧE (< ,IpDؖھ<2.RAcNƇjEAM+vE rDR\tכ&[r̖ѾE@JM W]PwmhhTAKD}i EG3߽]a P t4 7d:FsSQ&#=0uJ{Oޮ\QgYa늄; $!~ F1mjmIoxQ[qOpCdJ$B<[OIUqg`@ sx%T!MBHzn=G?EB ~~_y/M%/XE烗'lGĽ]ඖ<(x q98}v=C=noo!Hzɾ+BT!K)>KA^Kֲ]R4cTJQWl5q'{kGD^؜̵lY ;czKشY]^h8(b\FOVrYkl=A;ƭwsy3W]ㅙ:վZeⵞG0 ,EmZIY.'bR JB^Kr;"jS2#6P#;!ǩEս~GNNzIlPgqoҟ]/4$jd^ɋ \b{@!lN7QP7II5p5UOaǎn%(Pse%A^X+:ĤG HT5+5M2x lӆחPCBY^W\!eBV_r4n P/FU ]w eH}Ye!AŧKʏjmY(h@ zȭ ;I֫72{hC94Ԧ˩M3xš SS9VdKkQ B/\@ˈ[R8^6k,Aք/+O)-'í-KA)P#S5tW07<< U4j Jtfxnŀ_yFrUH\q7)\/o ]$梜FxC^p̉V?8Qnďm] m#RDjIrʼsU,?$={zi̼CcQx q!WĦdq?)!HQxs\Jdu^&_X{b|Z̉mkhP{S`^Tx ^ij?*iu'(#WLNC(d !MrO*[#Qfv}w]vm>JS%^!qDTXYC/#r҅4٢۸-6p\U/gqTrK ;H'soѺ,5%ղGTAr5% mEQ3WEhm)+FmiE,pg&<`q#z 6 Twl6LP )E&T \+uL[DXn! ,67$tEьa -$0]U3eӐWꑞ8O'$rwNyJG[Y4oVEPhh46[ 'ǰJ1YD{z-ͼ9? \ mOv>`5#+k\?5냷[pV@B +(5 ʉlhI@$ :Z zxu\?ttk?=O*a̧ՏZRG2Osl]KK٨C!OT ERv0I_'Qe=C]_1/ѳT]meV$>e&kI4R_@"TGǥB@:ׅiJy,~PåB|K.FhjԓuCrX߯\QՊܓ[L5 %#Vм*v:V{ n&Ǯ`[dDYtX"'՞_GOiHl»GEJYC[S@NӈdJIϡϗ5֣5 M=n1'Dua$'8"\M:iԨ --ۗiu^XjA\L<UD)?*!o9"e.ScQ^;jÎ:Jy[JQԊ<_A%WFp9v$"_[A8It'9 ZwA_%__@{6Kۉ]E{:T!žOow7Hj=GzP(.ۤ ơ Ҋ F(1JCI>νT!T!BK^\Bpx"J/ſyK=:-!eBhz~KkQN;o=4x[q7.ߞDu#ȕg}r%jR1ԁ]=9FbW>o/j0[0jG#..2]F= d;PҌ~pwv?QjimDy*8j&#= uDJr: i.RpKܹRd4I[Gm>[KXRP9yʘ #}'&ZuYEJĕo<ʔURAdtB66EÉ =&H.7iG5Ad4b$azJ C¸L7 eOԚˇeJZ"-956PqgZytBGӃ#qo73r_k]s: k.qRIσ!<PP>遥ulv j֢<4SV|j]ڑPJHZH v !D'OT!w;Q+bi #Cʄ-*= Za7P kH__UyCK:P*aUzzT!o%׬wkJHpOo՛S:ض]М%?999hkLop01-c V4:tH,Yl u +- /yu6`W9ps!;t{ADℶ -bIW涂t)XǸqj&oDB)6~h\[le}[E8tmJ5y;)nq} r̋FMV\m;RamU".RԿ%̬+h#X5|kr% V[#N°\;RQ39NW8޳|g'~&#l0wY2yz}1J;Jq[G9K?Hb|;w[slMX-*3PEJPGaCd'CPpa95Oi/Wx9xJ[#ΖYmaKJS9+n 6Ij<=g5r99}3=.=oZ=,i4Sf*BxGu)qts{aIQeY ;8ܝ`O'/ǥMdqإ}.8ɯ};E ,ƛI셾*W: $|qTF= ,Ot4mIߋ6sr.q~) k]W-ԽCx.nssr{y>u.?e'S;tWF솞@N>{(' fq 6]&\Oh-޺n]lG`y y-<]xՍ 8?sZytuSLm l8EYAN!qqwBe> tTrBߑ=zŗQjuhZ{bҁf1$N:VGkWuXxz^η.LDyL W2ۄt);lO Sy?+Ӿg7_e1[e=8%08!x|b≋씨PTfGm}Y[hd4٧%:? 7{yF66+lLJ̄qr+p^OM0ԩ˫g5'=GSC%xm1=u = 04}I> ^9νZ͎rϞ2|f=jׇP_/'T<7& j)˭->AJP\ xO0 jandx2n,׮Uvr'ٗI>YT)p|&p}?SZ pzdșP~Z2|%^m4iR= Jjwyt0>V0>l1E3o b+9Ր}xoBK9 \[Iᾨҟ}V˖k:xȞlsgZ(BOMǽ ΆV#us͞1ޡtu/W+P}63̹IcDH 2(/mU > |=GLO]+_KiR'f'%(<6Ҏn_d8.qPwqq'Iovl|r{ 23dT!̾>k[+VU>C,8xNgzC>Q:NtQ^>NOM=&KKmiq(I%B3I!%H2NCTAt#v$!ke$7quOa6%~oY8 5:y$#Wfw(ҕ0?=ǺjS9S8v4nWę#NRA;`bDm:#pCs-]o 9wp(P%jHzwTk{#\M5\:dG % )\oM>ÚB ElF _B;ҡ'&%4 zgqFΟnk*)ܕ/ay9ZZVbG$YȞ$VtEMg#PpUZg2GcHOAykh? ofv^úr/8Sz=wЅcmӝMqQ:*5u"\L6)?e( DY."tNjnwzR{om9Uۍ- I!'IM+RbVtj_wk^;A\kn3Vha{ s;"qiǗ0Ը'Fރ\HkY/CP6Ǔna4V!kKnr ~n>ܚ|#@ve^9 (OKOLץ͛KA7]?qӗDK+l 8OXIN \vJ@8 m99>&9BOBws터䒵u_\V?{(68_ 쥎o/^ Cy΂}M,8?U̒؇K~,>uz{wMT5Zm\_ )p+,z`BAx2Ǹuijc}nxt_|StuWǤ֑Ɵ7_ PC)%^PwYK'25RyEykq_0jxS&Ӻp9)R8d~²uۉuF(T,c/"HNSPx_[E2>C:'D=SrȑvrxoJ VldH< ޳?q g{a&̡'OPE_ D˒~ bBbc:X=sBU|%oDNȫ%YV⇢4 *l74t3}J $u󫡪aX7\P\T]C.\īQ&u.{Ura`]<_9 %RzA37r:J\OwDio%)o?#G@R}'~@["̺8(^R(R&wh>,f|ZP|3[$Sd'gZH3-,}='%⡾ۄHM酃RxGjʉaCD%GL'ā.>#yhnmHTHw (h1L\!]F -LX솘[%2Ym94hk$mi5ܫmuAZ m+=BNjT+GJ.Z!$r׌aU\fl^OZڹ9ҮP;?8.QʋL jqY8$%MdF~#sz [[Tv^"FJOvq?,ĒI_Fy_5TjZe;uAyNV.\3S+E CGaCb%AgB$T/U/U.Lba4ex橆=\ :{j0Ւ N*}gjpkuu '|JQ}OR#PJ2ㄮ38zm)_DhKh=BHD**' Tn ԥ;jJ #jI}{:j?YF0}j'YFb{/@k9lF|0^YSlݪ MշsF4 '6G LYtylGmGQU6$Fj3%Ĝn>[u' Ϣ\u%^]EMu+ )$e$@:*Z*!C{hZ@F S z@ %xA VЭ o'[!+`H5\uFKh'+щ7PIk {B3P2@ܑԊ^|I.k_9Q\WHAbߠR5B-m[ƅ!VvĦKL/^ 牭yx3QXRm$R,u(o4kmLfEe 3%רU湯OdfogA0].6R83+z]uA?1Cbr%תAs[^[-ťrKA5>4j=^K1@'…Y:֊֡}#YU#֪RQ W$ODHݾϠ.~$SVwYo=w*E !0$UG$e[]+ءwJtKJt[0VfQxITմm+pmq:ۋf]#2F3$qNw&h۵$2ƜI`:iꚽ͔z ^XEyp-Ie*͌#[­)86/^j_ _g7q$O /?*0F?GZITE{/ >X]êpwxxYyKcSFh%.qk66.hwZa4 XJgSյLoCP !<ɡsueI7B5k]2.nY8BGh]sQF}]k2vq5 Y+0 չvR}kءVc'{yq^@:eT$| >Z궾i/:s`AVFUxH2-vJr@[\w65.`1Fg)*JJ=EP5;b5=Mhx•\u5]gSi|/}ym ĖO 1V 3*q/z^jΙj-}gm5v *3QN2|Kd4R+tS @azTpvP-WYt]6]CPB Xq!8$$u5*STt&QDNTR\ՅNqj]?V)5MVW/4&#Yuf ~Hd s2TMb-/N5-#NTVU$Y~~*Zm)}kءGZILKjW0j7yasK<.ܬ9=U~Hd +ءZ]Ecomq}9Nge pFwf ST^%mÌ1 ~1f{,=fDR.}p}=TXq-DUy U%?{\-8{"&:ŧiZQ{|/E*y\^K.8*AﴧMF2:h8_G.3.# YnCuBƂّM/7t&/]tx^]T"^K#Xi)qqÌ- e ~roE*Qxq$|zbZY,\C.p1$ j6SYBL$UWϽ_K6α`y*&0 q%(})Yc ':^asd8mmފn*=q h~[]Gy C.@#?" P4]JW.(mALra6Nۧqp9~tV&J B17?/$ ߅Z>omU-Z?-\ykOG&W5?cZoư[O}?Wư[O}?Wz7Zq嶝ZԵ)wȃǐVM"7kRVM^kHAd,K4 t_8Y:jo400|ZVPRGβ~ѿ"vd[ $X]FBW8(q;U6:`KsF9¨,OFMk;UP$ r?ŷ_OXw k#F&h#`GJC.*1il\rZz}XД)YJ9[W=*!֎Y+rXÇe#郾Ճ~MKh"k =:xcƻMgh;t1X H.OGߍs"4jRK/Mc?hpK$\<1Dי#5 K,5vrAN_,~z(L5Ӵn&rUFUnyKnC71}s(b0Ôcz%5]TQc5KMa,#M?.#[yc(~ xE{RPݘ[nuσ+TM [ ZHb!nWXaDiA9r֭pڬqE)UTP:ăڏ?tUۯ /+ƿR<~[qm6?|HdٔV7֓f@3 q,g$ʵPq?UxT܁$h}{9@FGCB+|"A;Q>z4IVn9eָ/T w=&CIEU8'ŻcJ|*OTz2 R Ox8~YW@hiOU>t5.U`4 ?gxd  =DwrU*9ٯSգZ״K^;wDJp Hf߻qOP{d_  (KL9d{@4.+5{kUY"lԃ?R>ZImYGR3O֘G9Y 5_&ݩ~CBx7ֿ-vqFEf|z@NMKn"]*,2IxsU`1_qp֓6wq:[[[#d8cAU$*zHea8? 7}]{E?H2VشkԴ(pO_6(jbpz.eX\5x,܁2?3 w`|Ij7=W12&s=APA"piVz6vO),fSC{ڝg8ǔ*K#nd bhǀznH\%z4=WV4/;m# <*3 Vi9>4 jFI[g7u1rfeq&}]Ekks+Uȸ$>t)]٫qƆ ݬJm\XQL xER4ԴK-)(PqNx-etϴpfVz ~vZ)dWȮK"EB \""EYȤNI"NH"E-jh,{9\P=FD#arڋxP VdGE >uN6keNԞ Ѩf?X^=y|*i|&*l ǝ6قIh!e?;}5p*> V ݬ1#VnR a'\ފxQ4y2l5_{Ǯom|;ǭ{\j?e-Gz5mѢq/emT Eh|= M6&=gaSW{$lf~;glfm\xY?FX;Rr;=`StZ$ȍcI쭈v|p<9>j|3 ] nJ#8,@:Ofw6-P8tsݻ$~|1SEoV{L#-խ?k5g Ƒ~צO ~}M)?L9i{o6bp9Hh 2h\ i6w7p|΀cY-aR6>*P;yFǿ]?bx? xu0O*ܠH>bfY;B"F83k ;ǗIFnv:ݮ[ ,^u-|̼iֿ(TnHoqE J!${:QPU8裠E|Ģ_xfS:9s ďPN1ώ}OUQP_8'[o OIY}pUwUkmEnOJhp0]5\5܁yİ9w$⋻$Q>*u͖խUo­~\7oZE'(9jPK^?6?Zq ?NB:$ˬ`Na#*YezW)k~(psE׃.}&d@zrgo5cwTOXQhwMc1L=1Hڟs fm AdFG>"6.]~ׇtn!9 A ,.IV1pkj8V}CEV)#~4)I.ŸcL`Ļ|CCm2C֬G_=*1gJK,Jgbk ?OoҵItmQKW>aiz=+IcYFTQ*?V'S_櫯Ꚇ_~]F^f8=Q&$P~uac?Yk&܃<1# K,5h'2qJ %'{%je3YNZqyĿW_5T{=,-E#?ڗa?&vqFE //}ȯ?iz)Y?^ҵmS>(Ȼ/)8{K7Vuğ͗յg=%+BOˏڪ_ W*{EcJ74Մm'T. 9vIJW}ˆ5UfQk#A/#iOgmn9 {hH!Tnr8Tr=>vm;5jմM3^[]Zq":P Wox᨝\âh07{]g;E'v #|d |@0m@^Hlde!a9:qwT>c"rM~eQnԿ{!H߈<k_͖MER8~"?QQkWM2ծp56krAgbwi.qr۾>*"O%ڽʻCsl pˑx5Yn{ ذP<pαɧE) 凴#@3}yZeUGڜ$-֏*7X;)~"Dd s07!ywx䍀^5reH%"8P^ִ58䑤Dʡ jWi}F3%ihƕ1)o[cWqeւ s`1C;4(g+g¥3t[<駽4|ѰR)] .ʴ'qAf~!j~?ҦvamV'-yܿ*0}я? {ONct^ocJ7|Og:DrvFOo_&R{Qe'\(Zgio#A6}n/4f4d?mepjDT|^=/PiDjV@`j=G睇X7oST>L=ڇc|յZ{O"}uYtyxOY5gvUTdcl*˟hp'y_V-R8ky{V =/7/3ιzU߁?{jjwSXgۿ$pr8;Ǎ>Aˢ4mpC,QD_0?Vtn%{L4Qd aN|(gcyamu|K'/XN987.+ѵ]{D7 '%!u~>4ij^ٴh 7,_>h 7,_Ŏحi$PZ^4[dH,0Nw(h H䎆*xcCWvu8- >0ũF>*mO)ϲ :\>4[0FI?(m3}Qخ?W݂ǮepI~nwٿ=:eq:]'-lҕ|OqZEʍ}ysB$O7vpǘ #5LՠgUTi7T#"K&M j7vHfH8 35|YkWW:ZmU'l0Ycpޟ-P\{<ʫ z״xox-5LZ5SG$#)B^-ոNVd/@ݖ=T4G5* /Y_CZ{4e^oy].8#EMM5$,;eP5,wngjAi9{~U#CM+>9}.羷Vrtɦi^F Iː6d+_m-֥4qFcQOpl:UwE,$reˆ#5->\#/0#qRt>'c:.A/!XL|\gpsmE%Eca^-xY?aB"pIvVU\1Ye염0dj[< WPwڔim{'F Inȑo_[:s,()k8-u!4ۼjY3jݝ:Ӣ$zzz_ S)b0Qcz⑤꺽ƫykZ䫻h'9Qn?5+Z4+iK+H̝ۧbF<(67'- v}pmk@os~]m+M>\ahvu@B¯,+ZmiP~UM3rvdž7V.C5U垭m!ڒ~exʌz;<?+ujm׽EĶ>刖㹐r>^cRԝPm+GOoۿ۷CbGX-0ory[h;ϮXv=ܛ \خ?Aq5ưq0'K]^GQ$ˎn3T!Lto\y˫>kn,&{p}&3Qo:x[\]n $]6ib5f=xF:ʸKkQP$q &3 {?Za;m4Sƃ,$V/vhZq.aX́|}jݝ:vvyW'i>ޓKii쒳I 9 ;! \^F^3B&KFT!}iI[[jsLʬszslF5]TQz֌aQgDqF^,{u>,OS'ѰQ :CgZq̓ZԁU:($с~%+L&\?Yk([n r\p*ǐ>ToT헀.t! %Htasw;qʰvV6ryCc%O$隧Kpne}H4lOST.oa5KR~{a?E8̄FGEOХQm̺Ǒ )!ºsM'OyFXJ} $GIlhm#82JxqChuuƺYgeK%Ը9 bSE9/ NZsiSƣhGĊ9+%X%o gJx0HOjAacČ4=Q.e2KJА}6v7*=8kWUd8v+Y !hNqb3%fqȪ<,5xloE su|O5Rյ ۇ&[y%rC݈7M_!?[+KXze F L W! ;G]H!Hre=8.W=S"ԌΝı{FrVZ&rļvy˩. 3ipOS$Lcc+3.{귡Ɓzַ2HxN=-7pp冉UzLDŽʤuކEݢٿS;TukFю}ՎA$YDWϼJh<-ZYk\KwȝIJe 1 Tjݝ:2EZV*85n ;&8d2rs@yTwaVj]wh1zN_Z٦LΌwd>4zM#$ROeQ^Կ{!F߈mh&s۬Gy9.~œui<{\ ~]۔?ey#l>f?scn#˦i?x?#m g4z" W,|4OO&!qskC5`POFT z՞ômn(و妪=Dρ~ W4Ԭ4[-{P| w''^q?wi%T'@_w;H&dILmDy?7Vh~u}A֮ߒSG~Rcdx8ڴdPR;NXڼj+}џ;<?+tY~%=P{I\FQG92J=Z;1`jUzd}]Q4 @` ȴ~788_HZ sħvSwjrqoJ?ݝg\%EWi( :@XR>]>U8GF-ma18O\׬u~]j൅AF"g$8hkWgh 0??K]Wp.uW M-hyX'\g9WP=pFk8=.e\Ķ#g>5cлhh{MZ.%!k;wns.B`dU8Lq]-wʏ56Խ I'ェ)t 7t #>xw{F?ڇW?NnXO7Ss/_:6Dc"^6Q#O$cc/f)L@|h.9==n;9Bl SϻROj# ^fEiE-Q$)ym256YFJ!p[­Ǽx)]/{uJ1TwJ($xDaY'H.u<RGԷRGH_J꽦i|kC -w2s$d [|?Sӥ^h瑑% mR~oCibCo+lz_lmYA.$PF9 %fq.QfU=p`]ϤWخ?Wt!T=ضNQCѽAX/$65|VSyyikzwjUǴY\Yr2srv`HUCK? +ɜY G>3Cu#.#ɷ} Z"Յp+uA/#`rbio9kM|T-|+ ~kwJ_|`=2!\~okĜvyww$3(!7x*f°+7ZBo,Gڍ??<LaW- kKtM7fK\wK{?M$>'Rr7֟E+Y[Cu+H۝Tu$kAiVwڼNl=UVU?s h]𵮇gmzчZ1 Y[ʡ]uI'SQCZ[VФ?v{HPOE?JOsZ eisr}ͿtDD.;ֱ4Բy@ުm-fHyQzyUǍ{[}_5:\l(ub0J>fH"WAquh6rs-yuFbTrSEjjq]Xݵ7z SWƍ}k]t?f28{T️RӦ5gxe[#(99SqJ6dRH\"$A)dWA)SR vk-ԮUp:W]&t ޫ_߈b=Goh;Ƹ'%8&,^^%ՓNN12cNp'oi}λUVQ@`Rww8M* 4#s4KYK;cAKX, xTJZ+1Y\-NNx0oE&{iaӛn84.ԇH Yj;JLԢQ9OLI"@QqV$9WVw$0iY(ڏ []UqO!ۛ Δ6LJiEW[?C̪zRh[լH:!:ZWֈhlo*gG .z"C ¤y4e7(1>pW2TN.=(T i#3$www\OF}E1̪h:Lah i |%,s*̚KD+]MBt\c^ܭTyqB*ІD}or?*'۫CK76#Ƈ5 b^Ɨ)ij,PA`;$yU''{\9QG2$6왊,JG]\f:۰|LY" 'a}.ܩ85:xK;IϗZZq?B}*chwu=7Q$_'PGB+K6v3 { >rTFƫלAyh'Q!):F5ځY=qD*&3K SIcIWPGNW [hU-er^(X2@?Z]T,z^QvP+BW GدWYg+[)um Ae0#T%m4 =BX[CARWEzPBWkz^T!zPBW>tm̬L+|GZ^AE)iP.^CzW^T!zP z^A8Rrg&x6(`~Flt䲳C0Ĩ>R^5(#)UU\"kT(lR`;PȤNAuePLIu"ZI*]Zgz^$\ӔqP強O '㚧"+SinfyaGC#Vid5ml3HF;О'=+&vp.Z4-v㘍gLDR1ڲ GShk ҡCHlJ}#b<g5; 'aQ59+Bqo*`[xnlJCm5(D+|*n\@rAWo,\![ *ܒE)Tm\&N9 R1ip0F$>]KGj7 {kEz{dèI=M*XZ'(xrJcĪ +a.fAe|ꮒ0u>u2Ҹ,Қ7^(¸*}z$s(W[~\hm͚3De0H*pF68-Ķ͆ΌZkaj3Ē *%wCU,^QXL\:IP;nY7`ws*AI Mhm5ry9!d>b`^8-d`I}1xwA ttrFr*]IjgnRrCrRͯ^š,n Fn VG bqE=K˒qHTq'99(܂>1^Oƾ˂6H4ZQ\1-R6yFiX:R|c_6(zeTRk\#W9}!Q.,"*J^ޭF+G&ZVƧ|",Ք|M!aN/֮9J6,- WHAJڕuRd2 rNL_e:Qr*>h^o* &QR*L({v`/֙řmq^-U/{)SRmkeW;Tw#NI( U{9U3(}r +YQdzU*𪔸lWKDreIiŽ.+;B0E~{2&edJ< U&TyՎOEfj{ktrp| Lihc:%`_˭f? O)t sōEyo  ,4i\n>C#Ul().Z1FKV~Aђ)nUqGfYFcTup s/(>ũݜ@b19ڗt2#7t 8eKh"AH/^ tKST fkh;*ۍ+Vrr[ p /LU?JkLas֙%R\EqvA@F|V'mVGId,|5ym& I.X#ÛГ0G?ZEbeIǡ2G@9OJDèv&ܞSV'E`KOt&`p ~m=*$m7#2RL&hW¤CpPfbdS%pSɲYyxr A4ʰY)$]΢ZdqOh5J265[97>DAVzrFHj2E'(.R@' ^]BKs8DžJ{&6P{eFku VYƖmov(0T>;Y.>OOc|QұV ZZ&]Pz^CW5т2*+خ;jY(Xّrkl*zmN?X*w^2p)RʗF~ލV-zqugzNn aL|j .stCy:BƁ9xH} s)Mei§4<Ŋ:d-fr}Xe񩲭I,jL5ƞMJ:~u#z+Q%/H7ɀoZ1eڻ 5It`侙'=Faĥb$R>4N-uFapjwvǑ:v7xٱ[F^v oRR Z,H/OHˏZkm\Y..m7'%Oͷ\۰9;h3qgBTc4wvՍ Hb-3Sအ >B-tU_rsT7v;˿X}sJ!B1*Ic]n DMR7#m,9UPX9*t% lbM2KeGV&6רA@=vهhV9cln\1 ʙ(IԖ;Tm gb2*qMkS:ȿdޭN\7U*36%Fsv3pʤF䓹`&Ҧ$XۯҬ0{ytи&=ڦn9 & cZM I؀ӻE;G"S-.l#OCSnl㻋;sxGCYn&^`w4h+rxfr(xQIZesޚү`AsyJ,shd o m*j]Ȯ\w&|z;WL huqqSz֤AzOyx 񆗢>fz_% np{oC҂N1}e/FVΪ*(nՇ\d =8V\jn9ծYT;@wp"^B^#Y_ 'z7RӸ Gt+1բ+׉9_B6 U,^Gۭ'Rf(ʡCZj)4aJ9k6Ǖ ~Ipa6Kgr(rm898 xgQ=sǍmu;(`P0[Ɗ4䌣֖Kiv1cII ~4SR³._EBlX.AȪ_5c,\+,P=VEEnWsju9QH5ĺDkF­ۈݪENRx;YIv)$RpH""EB> 3kNeo epL75+˰ޡfu0 ϕs>*\4U.uk`Ԯ#NPrAe9}K*[ʒsKi$9)=|kGan.·GM!O3qSKPR g0\F&3}*O^99Mă*kyfI&68nwwiKyxՃ՝ϴ6"O9ބh.oyc[%FB]Y2MKcCd1*q*ߝHXZiOt0FnQc:杸]2X;a,P%%Z(V%p0\ |ڨk"1$ەGVkKϊ:p+OUO/7vўF4N932@˧%ɀiݜITL\&Q}(;\s7+=uA#gTtc axyrl A֢6B-5h(A@r:W/>16rjDQ qND}eH먿||P6~ĺޟ{Mx`ʠ3Zq=36EZr†ޱ&%^+U[' <\IU)AȭKЙ7#`ۀ<KcphZŕT)'H&G|nӭ{odaiic@Im#Wv wγv7˩cK($s;K3Mvp9ZRi^/#hvR>5gn*sU4YuS v;U 3R"c7dž(ss;e q͊+Y5Ă@|kM3ji]!Jgzs(p~FId cG[ȑ@ωOJLFVHY=:Z!ᴂRƉť8PǞ_eN-#?} Yքp [-j@s]_c_q֧BgqLjy + 5;¬~ԁ| Q6!ƊtV"Rކ5hR¬K`l3XWmY+wv7(@$4(B +eSUT6I:FzR|I*gF:blzu!IOsq#up /LӉ"UT=(!Y$Kv†OCzX vpT"C4?s*sIޫSXKk} ̥[>;Cqi,Nl d/$n4}m 9GF^o;f> 1ÁU֤Y͒L*ƪeZT \4 \"i$UIJ"jf|j03>4>\]ƛ*Փ0jkr_HHbI㣧M2F ]5ҶvpمV#>InV~t]hvuͰȥwHӕuI _,<=IlZaKҞ PRRHSȜJT]H"7#ҁEi: p.B_o f@46ީ'q1䌮5f|ya1kScҤM85n>ЈeR -kɦQ<΢K#-:>h4Ì-L 5^$,yGnFcXqeItc+Tm?RKbiѣG49e=r*a mŒZ4IjXrb;X ~f(T-ω][R̤F*ǐƝ=.FæF(<043n[l9YlzQOc0vl })!mq)qK@YIb;q>&bU,0@{MV**ΝԸf۔2Xy(6gvZ,PJ;=1}5"Sד}U0{=ƒ>u>IMBUD;YT`*(ˢF[5'oؐ gϨUca 1jkK-+Hֳ'lX<R8FKsG22SPf_; d IYC˘'4n4kBnb=LrWBQI=SNIy|k$ԛ'~c[#=+B{ydz5+LjǨ>T1ԂsI-PgP]c|UAKG{Υg9F+>U(8WyGtWjq) mNI,1TNCav+,>3M¸WReu3cD.C*,[TL4@2\jJ'?>_@8J6E#$z{&f,#44Z} sMcYfY.a.DY9RG1NU?Y4K WvSV'KAF6e(W<'ȏѤ2:=:m3o",@p΅UqxÚuȷVil돟#J.4~(ISEe{]8o} F[c ;c]RN)<M"8 HN&gHVPuSw⣢oҬšr5ޕ?QϞҌ)eZy@nQw&&FS NR#=dtZ=iW̶ysA,vX$%uP&Ga,AYf?y?i ",=H$h |WMrQzP]@uĕ& ~r(}{aWƽDQWŗ8aU|1,ZkTpqy udhъ:92A+n(PᛦaбK0ϸouRp4wKӕdmW9<3̱Z jg<ܣ:LiŁՙ֢vE.&k>rھ"U^dA8oiҤ$<3CѵK^NQF|DS5 0c=L3˒HYMS'0xb*.U\?6Cu׊Ws|pwG/MY*:44 @/ոS?tF$I\5dEpQP I $+|kp߈mXs ewKQPDҟk+ywW7k4`sx]N0¥LU<ı'4 X9NVCQ>OQdxYRF$>f;c4W?E e&kL%Qfe20E !)TcwV(ڸ1eG I`x$ϸsP˴Lr9ʐ~5/^1P G_ʆ砪Ρڔѫ-7]:tT;^[.|h]Y£O@ ZG`OuNՃFedQ$P- 2|r<>ծ`I3Jmv;WSuYzQXeiZŘ -n[h{))G9U?Fl-r |zyoC= ӸCk?gbʧj}:V$~iAUkM/ܿ3$ pz_84ӧ\nܜS8iOȸi̖#jrpH)o0WU-hoew/yW*k)mַ>!CJGLt6MbX`- OO*pA t" Q[̔%EWĚ(E0Lh<VV#A&/+QcSLf6J1_,R]no.Z3'%*1ȉTƣFS!zm22dʻnq?¢I}!yVyWVI;6Q9m#u#N[*[G#FlId'Gˆ$)p2}>!&eWG.[āW [{;(`Řj&8k-QUW;2E!ΏVqO⚇,[ WŖ^0YvP)B]?=c D\nE4n"^\9^#UiUdݧBʇw-nRV_u\=+,SW[2 YZvm]E+ņ(g|+$[ъivOPDcdbW!~Rv J0ca':qh9*bp*ۥ_UH$ LҐCmB 7vw$y9Sǐ|vwnp::mpS[e9q7qZ_,{Ú鳆|'4@T1;TK&Y\7+[A@۳lTxHy\O^EPvڪQ7w*iSn>Ps*+ n76‰B|,+0ӬH`1[8 L{ĆN~s38>^?!Z7j|+oj+2+_S=~5@ucԐ r)w>B|rWٱX\R\9ppr>UdI jD>19>)RHtr)cO08dEWI4|k1xPL;E_:gY*}!<WF$Z3NiP|qZ뉧e?ib\H1'8 qCaOEN/uFm5BҔ-ÜJӝLq30*nMg*5&Y'ٻ5uI],| Rr}Ka K[`d'4t>DW}Ι2b2p C>2EQΫ؞Y9VoslrMS{+q^G _ m`\5뮍;XEAHny'~ٮ>:V^_H(N3Oգ0KrX%߯9Z;Lts*$Ya:LuI{fX\#j;S]TU۵}Tc݇X}۞,՝;a '6$c$QO&2Im8$s_tmjQдKƜwV^#D(0Fk:>>`}ԹÛrp'i#+}x}˦n)ݐ 2Wc1Nn2wyÚIQF$6ׅ}f]Ѱ}*QOZtnxȼhx ܀Kd9jĶu:$ОЂ9xk $۫e˰IXxb0ZI8q%*抬j4 F;?A8 W{fI?I I,ۖ?dXܒ|:ggHBdinMI-"yWGPq4g_qoE,Ʋl~M</f8 fb ޢhs+?*xUKa/cJS֦_&#$Q+g8>t.V]"GlC(ꆓ%FEoK.m/b} Sc=zՓSB@:^PjRhO*)i 6"-#1ܴF+t,؀<f1S~5.I%g.J2u lH^OZ,қ wD_78őżkq*i3,|EqjkVjLoW՞[(ozjNI^84٠~$~|IѢZc@[LΙvj SID# >I@j.IUp`b^C+zBQPBN!&KtTXQR[wqfʰ&{Pg9[pG;A)PZkz͋m >Fp~fXj:+:N?t$ ;yՓDziD#+a֣q5,쁂²nycch΅tлC4~q$Ki'--dnt懑Tc ⻢\&J!rZ"G$^R$xTXu;4Λ{ďUb˂5j6+{c-p>5_,m2H̩雼i)*}u\$fBXnV[teGc֞5OɗBBf>RxRQ,N(@YܩT}vSެvѤ\^vT^lo֩/:j.ԅҠ;d̟zWq^:W]3P-!(.tj(??ܤĊm"E(3҈E(z\٨AWMqP2Hv9V)ZӎN6 ֐n)=ay]G¶~it i9AZhP䔖i'=W|E~o:7DcN|+%MEF;qz\a4 #SZF36r|qMı$3u# ֑IVJ&ml#/|<00>C ؗʎXbyp:T;|pxA44xa}jbcJ#$%V-~rHymed*s7T[@q9LrբhMӲt*ăVWiĈvs'?I4ҬM#g=~4;ZA$*VT چFZÝLyZ23i.aH4sl/e.9NLUCJ9SjjaYwvAnnXl[ FE+5G"_piI)'ʄi3$$\s]{E܆G'aW QFwHW1''EO*E]^N'-#Btl b:gyU;k؄gCәO}h :F$@)o$iW)yƎLJS_ky-+Rq֥ĺ?B")L|}k?rܣ*')Y:3T,n]Ctu6Z$S%ڳ8}3%#o$G moٝ2t"fq1$nbv WKy..\2ŽAReBVaҜzƒTLRCDG){ `(~%%S+HȽدεfgmQJ(bGChZbqY-҈0>UmqQ+”$ p>@Zjk\DA*Px4>s#&F SbPL;F9[ѽ0'55*8a,Ritg%F%3֪8w I?*ʩK*n Y&sZʖ 1KRFk$=sŁ;M٘(zWy6'ʞu-ba(-H(iEA< = A6QY^/o7'iRciBY LrUxNKd{B۫7š1YO";~E㑚f=t4ɸ&v$z6Hʫ|lt2CɜS;9^NU,Ǡ %bBQͿ§Ϩ3bF9U_Ṫ&[E4D}GZ}OܵA9&fz [hRrլu%7 p*@_b6sMe,i M꺵2Ow41³{gDA4{Sw?Iz4Fck$'Ъ~'Oʥrz#uxq[,P7c#>Cɂ FYK0LJZDl3rK![UD:s.~Fu 0>#^5J訧a. #I.rcrF!Qcc6ږBx,„\.ipMWT}F'1fbsԃ*cWD;CPXT\]M0ŏK/v̉ *(%G*rO mVOl*V7$@vվUJ~%U}b[Bls)o(NNPGöTH@QSc\À),7>dDggTG1$Xh#Ytu[܁19gT%W*y|d!QWdiE.Xg$QGyF t$=^aHlmA)S4*V c1fV\QjGLu| 8 Y]]L,9jJc6, h^X-3p6&v27<;?*oZ BiJ),qM^%HU5 ^Iجgo:(ŲV]HwmnLOFGaeEvE`5nh%b_vC'T_R{$ Vu8X=qXM[5c-K>V] њEy!4 䇑FU6Yg+Z7c^ԴQ*'_~>iֶx8;khlZ("vC ZqDmS~5}V+:xUp0G[hͥEwu[BY}g^MGvoj:UWx6-V"`EgeaQ>t9Lw*^W\{ӟT5+@UvbAn`H>UA{i[i,]/" .h J#`>c*'YruGGigk+Kʪe8HVM>R]wNUH@<ٰ{\ 4ɴKRGF]\3[/QP9VzۋkR9|KIP.)N( /0eytjD&(:SҲexd:Lղ{,+.Mᇻ#'5bIPh.j|N$J}k!5MʂNI5wT@H9yPcjW֚VbHv<,<z^%˓Pe.d;(\(Ljl\7 u@*Nr1u4P\ fbakYÒv/j<*$p9 Q }koъxWMT%`vfP[T Ѝ@ yAXbzflTuSP _,ueo pԴ(2A/UNCm1y1U\I&-S9;v+P@6\>>v ¹x퇇cJZ(sas[f0}<+^qw,F&F`2^cҗk3KpK])cϜr,2^Pe1Χ^<Ŝ=kq]CoDdbA~ :LOKm]Mx *wF '/W4Ve),K<~t: ?SmJ*E XsK1;)=@zowK$ tl;@vSI]" >XDGoiqFK<u0Wt]8q2JH' \Ǎ׸fۈ{HYDJKxUP0WFtkY&=>+z=kN,ĵe=Ҁ"!cT#LZhtScVZX.W(IfϾD8` “Px'4˨_aҥ+E;g -Hz/{& -ƑPHDf܊!k'}#J㗝W{Kǜ !bH?dxdKKr>Wā~$`qR*\Y̗FJ>'g$Q,zn"*hha K`L>uu)k :je9kHH nNqÚM=/qK;N[y[L#GusXt9[EwI3E!\~5>{j-Q3f'>:Դ{K qB]yB!ߛT>ۡ4˨hͤJ?k4rZIm:nqc=O:7ɟO3*:'Ύ$,2+˒֪Sgu$5)ah%T7-n.DHIfQXau[Y L|ZukmlP#;v.o ;敲]:d>~E9^\5P\r&?,gBχ[vF<ş}C xݑB<=OtoА sz_ƭD{jBE M//ZLbtŖO%maDd IiPB=6QYi(eS>9>4`JmOwҀHxG0;U]>w;^E l:Uۉu8{Mk!@u?֫&D-ygM)#e5h S$x*^H\䠭'؋}N N[Xn͏=Jd` Uj7ފZ{T?xߍB)796Y3n:zՈ|{G+#~XA;}N˥\c;rRXi7G> H߫74;D77 EWIƮ9-2rHn!n6(i7tH9.T7.s(N?I?6Q`o-e 0Pxj-st w[fg+FԢG(K]>!XYY#jG] \Yp>x723B.;U`*#>N%hb}ZamRV u1b6c~+̤dZq<(.}tU;c$L6ɬWffl;:nofi5d!9'Urr3g6t <[ qV^4񓊭cʎהOVxA*L (bfj+E<'OYjAlNB =SOe=fp`H' 6i}Som/"1NjiLd ؜r(DޔqQU2*4ʈ$rbD8\Ti4Syfw`ߟ[v\b X/|pN=*w6`wR20?JXhƜIʅ&kWBt)|`k1U'&fs99Ozi-eU#鰙n眃ʀ䟗UWaȭ'NZ,31$$iĽysܳԝx ~pUAWҺUAHM7EeE1BcRDd1?1wgQJG aԩ|j%-ԸVV1E{<*>1:Tռ+eȌA#)>ž"iFj|<}jWgE՚HPWJpFqL/*Xݠ0\GO#xڠt9VRxCR]ŗST PMcU;{@j g㓳12-rdV۟zѸP8?BU6}+O Z=JQ\ccdqn Դr7 XID˝ϖjw=8rUT~$oo5ꤗxႜ Z*aⷤU-F`{3Ƈ(A6?eӮN <2O4i\y[„VU+scSǠZɦhѻ =S-yoJ;*L{w$)N[ 7+`_ZLhXֻ"\W/s!HI*mdl)c,ܫ|i(؝ZBNچZaʨ+P7W"qFuYcWe>_>KcETaLf5Uϼvu4@s3\gNe =?>`8GEd ܞ}jbӶ*LvURy-gw?Tker+= @)+]3]TQ@Q:ϐ@ LvI{1=(E&Hk潿w!e2`f,~nY'{I*P Q xo5HZG YrBsmH 7W+ݰTR'YOpouG%We2.WW#-Tt$dtaV:SKmr^cGIȔќ\HFTQ3OZ9G$ǩaFz9Pl'Y$xzT5 95a1uP~+}sA)Pqhl3hqGNc|nfnvV5#8 yXY&[GN (iDj,URDQҖI7Ƞ Ǘƪ:Ei,CʀF1.tJJ/ANJQ쿚A&~'yH VN$sF|mreY_O;VLNXO]2~ |vS ڴ`qRhh: Kn*|@|,7:f v,OEIu/GQʿpκ79Y9]crsIPe a Q $aeֶgCh r%?pWaEFFc)\ ]r\2K bTcpV)ʴMMOkx%yHvhHFY#%|zU|3Ùp:Gi@*tlB4Y%Hj|1n¢h bXp6Fԅ~pv?oR$ѕqO \iQ҃E b%>@#ִ|vlxoV+":-UUdGV9=ѽh\Uh9lQYI!w%F8QkQ11yGƂ kv8ҳ'/RТ_*7Q.|3N%nwjIY7\dO6%hv9qf9V^X SJCOYQyjZL^.62gmtڋZYx$.-̅9SA9VwUeV #Kwǣ#fGccPP~idoI"OYU#F6 ^-KRQnBqҰ=Geэ]6d5?Sk=I)^>vÖ8Q쨇b5#26XnƸ,dh##1aJ@uG(?&M EA,#SˎeKhR%Yel1;/)d-cCry4!DLwpv>Gj6s25o1RlAr >__<brw>Fݢ<`H9.S4rPǢdz[ʎ s2 r-6\,qT)}l umI[l]FZ@g~e/ʣ}C-#RFIBp>96d'Ke|~VGx͉ rwN mbpe~u&%S[Īb9JspA*ɬŦpl y^&bߤ9R5Zw&,s ? *}I&5rz:R%lB5ZDoZ72fy+89ޑ!*Rd=FM4KmYbúbFOU"X?=$} 7bS3C6 P|sAc>unu D>OUG :.k]O@ӯe7P$;$+q,Nξ#*?TW e 2'B=)׹a t۽ѕ 0F#S{VtՠA(1!2Qof|&WxR7Bt`U@Gh/&FUJ<Ʈ g% V,|B{Į7=+p' h٤u`퍕%yIh@Zހf=(u,D0 `w n4Rxf'D, `Jf` 'l`VSg-͢*WN EsvKhu8 Gebc8SΫrک# `6K'1n^P֮/o`/EQ ,RofRXSY?z\NUsA:JV1 W]{yX9 uoXQWCỨ~[a8c[<\ n[9n~tGđ&<3>+cV>#{M>7(l'٭K`*9g"@ #!MH$5e?uIxF57KlT)K3M{QX?@(4%Iczڥp2@;lj>5iPIL)#s fZŅC4xmPBF~^U5#8"XߏɋU.)`ҝB9pH)@C8\ΧDqu p>xΨ@u>@&)cFg#Z4Sܞ2hnÉpT<#xܣs3("3?蚋 d~}+ex`7z4u pO2As%:ƈкsj'qˌ? ʝzd[%@,43˕M1I64WZIN{EҐ<\;jqhWh7\Z/]Pu z{ F9ÑsqZ5c=@ک5g[\7e/4G@rָǧ͍@.NkRhV<,Ř.E-JilrTa?&zm-eϞ ެ mu,ŏ5ŏg59yr,K'Qܞjtve޺ sW Kژ>v>YV@66<>&@ R(>UHWEfc!ͽ3~/*x՘< 2y]|<(}Ɩg+]lE}ՎISBʛ2C+*[GM*^%$Ğa?/B*h0yHͨhcG8B9d b U6F}'SA#8#­vcFҫG#6'n2UF&pEYPF^hF(gcTf'Kˑhp<4 Ye$?:/F2.}7Aj*Np-n'5R\hs6>TOz6haxCmLKE+;ҭ57I˽ԯ1Zlg'BYX+%Ν'4n3muh,֎}rHۡ{/A^]xrW_*%8:t1@e!ADp:|ig`N1 1[9c#>g֦ݫ%HH_wφjC#.niJk7LUP`u'mݑ̧cSjMeBa9> hd.! >(<Ϩ6"(g@KU'$+t \E2F9@ia'P5iMȠ]$ *#pwrD@zoվohGr[@g!/ִ7[CΣU>ߏ֩|=}YXVmٕ!!,r7$ĵdJ9l.mQ y'p|1:U*Xd0m;8e$P1OOOBd "xX-+golV)S(;LKCwZAkAn]bi#fA+Zr  L #4PO5#%sl!\"Hr6 ‰D*{d70 e6*|A>|NC("-\YֻHW-Uu[t5h),P|)bm;-:૲U빒߉PAȌ¬1a3B.-.G$,N+jcY\UD2suI~˲'5ꖗWZl(NR){jYL'2gʏOBcZiD VR7;O)5 r9{B:|H4|os*w"-l3.F#ٛ3(>$}H99>@(fj䛽TPC.GQ p~\*J0d*zT&么0K)lBJϏZ4C}TE Q(1Aש[ uK@lU+L,sUѹo%Lt%a`r27dy29K P$]Ԍo5i:uÆ) +)R7_*}ZMK:U-%KyA\ywYX@x '6sݵ܏1K'XU)`|E>09DN06>8a 㚚I1B%0ۤ~9CV?\Tذ(T瑁jB;&Y\hո~q"VSMucr|8?8 8^BwFTEO,8!ЌII2WAp˾];AԉgXbiPbnXV};*.1l,q$%$h$f4U8JBoF,Ul\gk c pc9UM7*A587RMg*i -v>;aqEqzе UIzRH-Nht×"#U֊ ;F|6clzSW-mZ2Ӆ'`?GPa5Tlԙ$?8@mJəA(uͽI%aR.5k869@4*_V$oI)z,99mԫx.5[YdmP6g$|*4w-(ƜXZYDeً-9j/e.YTآ.j\#J no5[{a6󫾙ZVfE/ǽ= 4.|=|b($+9%Ԯ-?f$l9F? \g2,.Ie>gZo-AK]c<Sd剹GMf"^bU=AS?須UNyӈ-A)@6]ʫ1k4yOeΫFpT'9yH=v='4*A'Qs +F 2xl$ԴJ.|$> 5E]RZIPzQr*jN֗'[#zaj,ݺAXjWS2qB, pTT^\ JǒQ{s`j{N5` AYMBYBԆ4EM5;Ƴrڛ0kf-E3UD MZhگsޕZ칔2w5q-B?pk7]ԎaH1+4ת#8!Vż!'ʧq-X۷Zh'q3Y[C'w*nU 1P>ʌ*v~y4"&(M{LIFꜞȐB;w;/:w"{J#I^l+ 9xit3*u}%B2\F`wp6IѾ+\}Hb ƁXm,w>uT-C$F[WjؼCNwnGHo$W$Qn{UnX;06K!$w2u *|8 q)ŬӰVlG#@V>qb2N3UeM} q2v#cҲey%gbğ2s[htJ4_fI2>^cSm٧ ]vHb2F}jߓz~Ǹ`rN ?Vؙ n/NmnU9c# z+CNv`T8 >FʂdMݔC:(lB1җ=42+ܬ*TNj%ﭹ"tAًi[: h]:xyY[5^x)+r $t= Y/A ȋ $nGZT *DRmq,J{ `t}{[P? K;83BAkK&yӘ?4Tl˵KT`'$GC2(rcj:/0$2AU<9Z\UNl0*d i$''go[-ʘ220 auҭDSWE`0bZ9Pȓ%2N>VH!Ii6SxFPɨ3#m `9ȭX7f\2R>;+JGbӥVۈ`.Nޕtӣ)R$Nr4 .XM/IU&Z'k6ϭg${,\' SP`>B!BD=F.IUGx,Ǡ957T_x7졋Q^F:2DqBtV>EOlz9;Vwʕ6.75esOkv6S͜64wcqBrzFdH팒:˒j񝵪zsc.]ǂg QL*֐ta{gn+I]"qR. Mop~bLxyW\A+5F)t],4,fK֬m&wȡ6|cq^\Ep eYX|8>\i ]r:ySL3Z,H*mJ \E^PvQOs^[%v}RE˨=p[?.8zI̥K8]r~fK8 %.0Tgۥ69 FstWO5]b$H{hll7|cmcOYA:nEQXO7\-8{2+.\*:^>9B VGB{TvANKg1Iy1yyw4->N}}AME6U]>BRN95$DM;C8yr88>Fׄ9gY(ѡtnW“sVw=Ӱ9$#E]?tVkk/:TwFh|>%ʀ7Ѳ 0i&GOK!ZdKʏU[C էg'Kf|-!xAfDWTOœnyrsWIExNMQ1PxSqBuS:I? gJZ&C3`x5C,nFp A|缂7eBZqSI.RB5yn @=(M aPJe\=#6d4{uHԘ"[Lq]!Rcʱ*!sHܣTYآ2uM+ZRca%"i>q2ƅQTcSSYg4U%lv:2:</3o25g%>BHmwtnAlQt@8 -:L{t-$H./˂ᷦ_rrDkW=1 @@sT挤mZ[qb|Wά1w%@ c04)b76<$@s)ه%d{6Y`,uWU*YХIfbZ ?Xy|EZ4-S*l՞[6*N|T@wr"AKYmOR,,%ҮD ~BLg;,~Ty~6_Y74.j jlWi!#QL+1[ԴU2De#^+{dtRN"ݢzMOfNK 97Q梸I;R\894ZwU0 7$TYYI8Vv77 VePކG MvȤT^+Q~M]m&#"Iti{5~mk@Ztn̝Mf=ij=qަ}*x1 M3V ;ȠbpYXCx&͸=|b֮o`ΙPKM+&A|74e|˅)*hv#MHH&G@@}*M8eS|wT)F^`1iV۱H:ι*gt# ؠP%Q}z4$ed6 ZУۥܱNlŶ"*o=hC U`010ſ{v6 *OJ|GEڵ F2l%[2t{yK#+t#ZՠԑNӵT umּSm| Mto Yr ݝyܭ;gwwD12~;՞-:Ӆmgdܟ}r9Ә|jfRp}sҶ"Ξ m ѵ+hۃȩD$n] >nt;"Cr2GL2pΥ]g͐0pOyVB}4Re]6$gĊf1$<"~reb貫A"g?@s!HY)j2OZpE̞Z;Ei|ݘ9HZe돭g}* ~2`[5!^3ⓛ\YQ%P HXQDА:F4-Kr AN`qeNA0B9B @$Eb_uQgҵM,4of%I]>8SX8x30I(^MQo1̑ޗ9K]Cs*) ߟ|(Y{srY,@a =Bһ481;rbrPr[ƣbgV8 ,3 j 1>*5`sZ~?bsbiDc ZXrRas<+zg:H-k2K\Hc fsep9SDaFXBcoLm0 S,v1s)|TeP+}Ի6YXG"d#@]8<#ݩpMiHP$Q}S·soxXcr~7D[{qJFJh?:k-T[hUM.q i:Z[YFN'򴈖1A Z’E)HU3b/'KZ&b끎7& KVQn./hnS†A/ 0ڗgw$uX̳CU)tṷ+$g~#.ӴE(Σ aγ.-mxk8[+FiKAєs $P]VYk{nj?*tǍpGPH4ny۾ C'p9UM8gsxuɯWjڶ$ sГ\$R\+;tלwS4SJ6V.KH0Hxu,Y]K"6N"Z.\4$wpr xX2A+j9e5qmMnNUHA?ķ;1(WNHڒ] WH*i5-,N FqPq9`M5.K#$-SH-'~7bI4p'y؂޴֡|HǥTihtIUR@PH#;RUY^IR U$Amss"ܹQ˔f{` ݀=O;}*kg[dl9>U:r\C|yҭ$#R2YT8 h\ΤIܵdz[siUK^ЂtB"X$WF7ם`9 8Rfu,zb$zҮ4x Rv%[ iG]$< K2? eAxuɣB/T+m`~c0ϑC^=.N3MVL44 v4B=AXtx W Rpոs^3ӭ--4q*ـ<67+sN'Xՠ.vld`JDӪŒ 2t:jchIC4 !7Gf+,a`W'cWJKމQ$d\϶WL =7 +lrЊj:n-i*jМ'YFh6пEJQ|2C!{T/S.VB$U4K.@-#ƾ?dl('{/0]ArToCG=LVQmFq?P?}Y[HX ayGy0%źi67ij07<?x mX7S:ΩwM) 1% gaA"9 Fqq)S٭.KD2a?dEO*#r2Xzy}D3OҏǨ`yl'VUn8[<.* 'Ox=3aF9ȼ\3ظB;#Я߽a L<jdtLK١8CJD0>n#  l1H֛*lsHL<腛IY qvam n$U$ʩ*:bCZL(8V@p\갴>s0[|igʏa0.YoP- z~X&kF\) K@Nzy*A,3z K{/+-Sf:38>H*9G1>aM"r3hk:ϦJ7`Yk ANWRSҜMO6jӬ/u7*ݍ9fπ'@M^ >\l3V}WAM[$LYI q>]r)RzAkm5~$m[Z+Mqpy>45i '}ۥ^ep=wnc#ktMDɤ]DxcI-Nae .Ii)=.ʿEq½pҤ]̟aWW[&V*u'|j*29FJ>UNώ>?p B6Gv=64)vۦ)¨fy(+"/dhPN|RIt>4$K6ÎR|SV\ZfѬĒS~QYHG419Q$y?uOQ(ovc *=>sD 3ᰧL #.wR2=)m@9a{p߯hjO%.N#sӝ# q@Ȩ('Up3i3{T· o?.cҴ;N=ì|Ĭ8$)_Fpl4yt1eiC nl5z q{议FDe\xիOHW@A9- /-Epďh"fR++%u,:)on8XXE`"Ɲy-`æH4jNRA+D䇘5qnK2[1T |,Ӟiz5+M^ KUXӛsV ܲHYرb^KSc0|4ؠA>U&lyy6e,T]NNE}(bB?3ʷ+/"kV:eicN<9$rIQ.9O؝@Npgn'p:T. D23(`V#mѯu~gRbƭ ` xA Оlhlԋ{ Ku~} \i;fUahn2`H.mԤn`uJ34s$#&zi7h~l!ҟ7StME#bzvQ<=WW> G,ɉ&vzkĚΝk5\mfCG(au`mP s4)ֆ$`OkIO(gۙEq\*u:BCq]29t?JYv2OAU҅9z v9WbCĜJ=<<) <h,0Hm\Kg``j8.4RyO)oAt9Lex/$¶2,dJ4^r|(/4%\SFi`6Nv~(#֤7M33\!ќjH7{.:tF *l Xc':#2\W 1sO3LAPih)Y\o#{RBJsB8 < u(]ar-y*xr@yϐݒrHᓸT %XES쪓RSv,+cs坨[ģ*:Rx)*47Ϊ>G.-^DUec2ўl)fTlIaɱVIu[֕-_cT!@;dTS5XZlteX}/ozfF4~ZVmIqdhQΥyqwȬU0K6MVƏ˯G/ LzYխC,[NM;od2fM.qzU;gEzU.]V2`e*sjcrcy]SYy8qEum5Ο&ݚ%֩ZcBX7+7[λ55-'(3- K7_!QGJ N@svq>_(%#P'55#Lyf $Nnp[Cס1Oʗ@@'Μ(Wlf{4ސ~4cJ[ n`|c}6dΩqj6I2ݜt+9KmHcEb3ojM^;(kQ`>>)4:0w"`f+VbT '*lTϟ+;O;uIdi=ﻥK,rl1EeK=nV3DSi&'#Gsۜ`kX U;Lc,GZ466suL ,.?yй_,OY4qlpb ҎA_vdaOօ['ؒKkQ =3E-mqN|ه&[]pί'w|(FX-eVNb|+4`-8ṳ'ְm. =OAWz٣oH!kg,K0',OV>V6+mB*/LKugXM|)Mt8['w1UAQtYـ!hSk>`1}RiۖP61kѭgՅB'7+L&>%)oR/2hwCQQ'N [??N-y8WҵbcUۀ Xls=wҋ.wh UYdgEYqҪQim?*v^ bmc@kr*maGʀEGvFsf98 lmlhqѸ.' "obA W")5/rOG£j";fҕ nc9RbڜY<֑e I܊ {>ɭI[l_YҞf$x 8`."TyU#u}"OjSu*:^:,HTKk =ۮϥ[4w? yc{`a {lE1*ʹ |`ּJ"nD F9 1V+`T9s+LX0?qfz{HFUT| @"Vж#d rCTs7/|1DՕ^`6K)G%r [ 2ܙI<̀GOZmoG0{ےs6Ǖ9{4g+@=u9/Vq0$W/nV ido_?pAx-ygfBț.1;LՙS*ӣbC gԌևk{s4BN8'qwϨ\B`YbURVFh{ERe547! cv4gPL܅R0-u$ MjcQlB;o5w{ۅD<^$S+8 mtBN\i0c48"TP_c 5OԻBhcbORo.-pfdKm8 @} "8=6sx# XH!fJT[uF;朞WS']ӂRyeڀɚnO"b^'7!֮]lWƩ|:ͭD)L͞-%t?: քs:A{xkF REb7K'H<Kюۼ`(b:=*})4l@>Tn-Ī` d>*)Ff,0@!45d*A')R] Ib^,$ $/LK(M6] 3A>?OD0V~;}1BpIypѠe,)#+M;E'̆%^l{GFD8eYz̵NkQ7>S]2O(59Gsj6-PH4搀9SODiU.۸B0F:i+DVBvfߖ-u]pF>[S3=IR؋8ۼҮs.MRUl;"d`A_ޱVT!TyqW. [}Am†9gI9>Tm%Y-GeRiyя>ZN4`Лq r[@aʡ`A>;TJ dRܞˌ[%ʫbObn8ONԡ1M>Q^U th^y2;r򌁺MK{TSe:H$$$1?K #9xS;VVLt!wjY.h:;TY@3r1L;M4]:+s,.9Ux67 :$GbSG>K\N6y \ގ*1.TTu*˥6v8ڧZ4YwRFd`ԸNGPli:w\=D4 R^w`2@KU\l#'=^ʇ.b+B["^y?ԨwXEE!fWv@h72IG@u+thT(%T6moI!%Irσ), GGiSE zsކӧ1Im,1~Y<74uQiѾ2``kHDKs !=iN6=TK}Uc<+R'4cyⲴbID I (pwN^ &/>Pcdi*zDǺ076}<|k)<邆~M^PAo58J޵FN(i%ڤF! mjzt3,}0$$A#F/2s?ڱ0I3LNH"u`>8L(~ncՏ>&d:BFv>SepF1ғ4I,| i!"pzxtA1iNنnl XQb/xY #ڤA3<׀jEU2vw>4-вܻ jDn܈s4C$̳ *zՁZݮaWKw4nvzUrGm܌46,֎h-|JI%yLLFu P[7,оmmHү_aV[IMw$sQʈNeGluϜ%=>5*Kɒ|)&M7/K& ƣs}(ړ擊*w\4G]cA5p)$Iq>2d` dSϨ1f _K3/JBX(b⿳'H;!С39$ٷ Dv11 1G ;荦gzTt#4F xc9)=9U8 }NG]Z$xV;j/HԒwէF+<끟:˒2u||a(;j,U__VٮQT6 8RP\8SOrӃ. b7{23'V3tIؓH @8VН`sOAg##҉ OMdJ?7a?*j8٤d8b1h$=Sgw'PY 0qDžDs+؀NGǭѐ=NxJ.)Jwocj/0eNbﺨ>FDH9ܶ>5zNm5{ Dl}ngֳrM3 S$yBu?Nx흙:6Nz9pErT:إyv5hvN`29Ojæچ!O)⫬Id>?Èזy.=5fxoDa3ithDef_]$VtB&ơGM02Хx ^RcitۓcN{"X "6wteԱޅv2c]" H^q@ \utbA>UHPc1liZf$*Pyv+/GQh}(h8Y +A&$), qQԗ| Ai)+I<u#'jnhdhx?umj/7[B_L޹5(,|65\t񇧈5ݣ PY4~>دУh?ir"%GfU>?z[(|~5HһYҵ5naXV=3#fU-}snzj@(Iv] B7_4J0*EUb:2$O[w,0} V\culaXk96!ۯ7+mʈ^vڤݍ̎ T; Zxܷ_z(IyXPl:GldW쬀sn?;G<̧-#b<>N\qėU(b>il"t^WeE?n-m3%峞Yclpv b0E^4 *MUmF$7S qqVQ(_MVȿ"E&;3Jl DuԴyUǒ5.@]42ZZ˟%HjzdB6LoV̲:d1%]30dwV ?UNC;CuGhcfPGF7v7qU[Ro3pi8Xv5ѧ<")}AR&':4|Eq}m=("—i(] jq,#iCW=6m%['֍FWj"F8Tᔆ#Pdnk_Ѵ{h s`H;B˴gA})Jl=Dǹ%zky06YyKr:3eI;aMW %Dܜ` j`4l}֬zў.ć|ZK;{v ?4-4;ȦyTc|S`dx׹3Ո#m"QWMӗ7N6)\1 RJPyoUD:ЦDD6yMz#4x☒x8; W#Hvhĩle.*mZ!P Tutւ9%+dTT(cW^$AɪElί|:U3?ՌyPYTER"ўRwD9bN|EiEf;MIectVXMg]쎠 7RcBI~}NźkW+l7l{Q^UB ]g*V Xg #=ʬzF5ėHV"ϑM 間!S'e?>r(6V~A·֬zG_ݺq)2Yl* "J mEYq4Au$2Taiݶe-Js1֨B5-կYnX!?~(I%H)96᳟$Q]1+wU{;W^Tҡxcj&GD(){>) ZAS4ܱ2Єߊ9RUp3Ɠn-w /# ЌBsF>d5Fyw!v!>&sgH0>?vjFj K d6T2yN tǻcOЧg;>d<޻UȘ0Ogbg5r:ixӹT$<3a }YV-onej,9I'ʩϵ{r9}'wxTEiwdh2RYJv(FlTC09)dl={o Xfb<~A3 LVۚ[uEU#EdQ9$+ i,FvΡhA EP:X&-[NėW(FYFM"SMNcC ]Oyu!|IF t[AB@QR.ݒZT(%zd3Ջ/^D*R>@NGՈQyT|CUՃgo{gu-PQ2jݭeZ0l0v#UVCX8>ےwl6N.rU+[mKHՠZWʬVpjˮAHܦk)\*N'}?(+LXTU@C;d,YSXt爎uƁ^5E| sRV,Wx$a1E-;Dѫ3`tUH)o6)WlCD̬1îuޠú~ .H'lg 0N|MK0*Te{G>CQ"C=0>tE#cH|dn+B>Cƚ,_3aO!F'nȤ25i.#Ѵؽ^@OAN+T];5qsoSSFȡ4c9t#2zNحj9TS6ZcTfTi k88jk<e W$g˜7ߕMwCN)PVIݏvSSicBX3TyQqE7 ʌ(T,9uQoLqpj܈JUj{Iu[$,3oZ"T"Qm[ _P)dX֎_hvf8yؾ0$Alt%YK! Eqs+:(^[$/vYHFIaeI.%I ,_8sO.4 +txA*GiZN5 j6 ]Q53) H8טfŃg5HHq\,XoRa(*s`QŘ5/q\pgqOY5pPݒ-ߟ7$OkU+Úvlw n:o $^ NxR'SIh|EplMQI9 =^WZB7,Nz=0Ƀ2?cT=pAB[vvc(Xx#joI >usT>١U|D{)Uc氺H|ͽ:/B/Lc#!8뱫,Mh̹ )Q5v֍ߴj+q 3NvPʹ7W;dPkSl&r(Z = 9sH_1Sblf3՟&ތH"}AЃ*Eo]ؽ i1f @HX EICiEKLxF74lj?h2*"}Q3m,HO=I⍽!mИ+nC+KҡQk^0+f| ?p5&wp@̎|xp+L**Od}..bu@ xV 8lŜE}IDfV9@0-oT*=qxN5\ <"(ǐÇm_B2?-S^4OSR"\o #}6tOTZ+\7c76 gUPEGOѮչYm,ARB>GtB܇f'L[{ c#<ɪeJac%K ]`/SQ f`*2H'ɰ?0or#{`Ai.&]OߵMӴӡYYrdflC*}~oL K[`6Nֽcu5Xi71ppx~QC[iNK-V h/ vo?njEVI=ZU*C"S!<ǛoFt= B)@\(t"ܷ .m>T2y)B^m*f¸fnʚX3RB!Qt1L|iQVA~T;Ti>]?:_䇽HˁG5DCu%})bT9Ԩteu -W*|ZclTb.mZ E[uA'Ƃ3LY{`G{qCg#OLfD(#E4ici^&V,AzBr Cu9ޭKT|w%vinA7xTGD2D jj9UeqPbX2sVixBɜd.MFD-)4O n@a-28`fh.1bAH`HhfTvFp M4nRYeV?4+$7/M-*I4b#1BE=20by}/<]v zFtn X͌VWUyYX6b%GO*)R@cl/ƞ Y #rZvg4,Wl%~e0 Vagouy A.|_oJ\V_–e/qgkg./$۔0P xC,<d֒]D[Zx:E`܉#N`18 n? %ܴcyR"qLh60Y||HC,s:9('S'8@j&9)4a6"s4㛙rG#c(W(F7 \~@~N"'OZ|O}՗ nٻP #n9ǕqSAMS؍M9 ȩuzŒ[?]8U BeL'YqBmVU~F}@I\A`s=wcmosQ+)FOʪV27xZK??xCUcCHl,rr3h1=Nۚ#wXƤ] <> mi*j>?JS3sc}$$(ʼn,KKGea£>4o▌+B1EmNBLCJ˺>%譳 ©;Q Xh$rx-c"Fe p˄aЫPV݂1?*vb$h`WW||sJ9"N`O1>ϩwdu63RYdJv@QnDV+~hSטrQCˏSVټMhnuGX`R}2෵i -k&V,_J@-a} bX[MvZ̠W?-+a:,UpLXjtmz%Ý/V8xצK8wgݤJv1*)+k2EOhxtߜv>i+/j-)?:іE1mcO)l*ZBhr)<(ڣGMy ͎񓏺ϡ,IҤ ‚.\'-]+Ɵsq3Ik,M=nS͡Ysb p'鹢O%hG1Y܏ЍiIڜ(;Y,0I,j 7ҬW^U/REq}3B3Zβ7_{e}\wjT(,lp+Oѧc1>Y/\or#RB9 ̤r(%WAGƕjĤ*\Yb@T@,6OU wr}XԦu<4:>#nڜ$Ss)Fz: ڴ6](ve\oPXn ;ܹE2F<- bL TppvնǍH.Øuv(m)~}aBtG͉d]4>SLD|4# vXk{ӿrQ ٿw})^bZW>:cXI/o،C+Dr'jsiQ3wU.sHP2)'yF˻b|I93:w/+)ǔjAo.`և^а9$QVZEKʽ4}rZt5)c:_:f+ zryW_}HĶgR>5i0O|޷NƼo3ƫ蟗ܚl4&G.5:7sL:mY#ٷ$M!"^E4xW SEbeRqRVws8 KѰp6 :pGp UX.ᕑjq%17 2++r5fHFHaBW/Y19&LWNg:34e?*t+ʳu>K[M-Bee\+C67?(U`y(KV8IH4ᮏ+ۊjp]kAu^ׇZD;o^|y̘sTZCO]J A֡sdbw!9aStl(XH~/Ostd0 dS1@7tި4WMIm4Ũ“Nrv%ⴐVE1Y.[qթPNBCEm5 ;LS@csn ߱زFRq8ZIAޓ#MZ*L!Iޭk?Ӯƛ(*֑SOqI,|;Y._~|*ަpI©4qG/v*18>i° f=.J;U}GAUӠ}Af9c/ \mk0D[d_70P[SXF9B(cTC.F/.~T|[ J\FF. sg=j]*E~'A(%$ㄔt@VE?[-[& }jÙqaKqˏ܋nUk:: qq$"c|P8F *^u,NHfR?yʐ߲gWh/.v? vN2-^  ˓u30=8Wبi\mctx3CuK(jzUͰSr0|lU:ks$<ܬ@qЏ &uĂy_#t \W#vsmlczA(GyO/-L?FuVD!6 l2!aS6R,ȇa>$?5.q,)]@**'L(b58W&㈮[w/,HƢ]ݪf<7Ke'VK<-NN>=+sfMr;Qg*ާ{Pr|TY9A/6:ԍ=| 0"b/##Gѻ٧Z򵢟)Hw;)2^k@\S{w=%DqWN% (x+ ]"Aq%]lE~4 Cư<ĝɭ-9K-T}E4 r=(isD3Z3g(D4h|qGfGW (ZpW9WM6 k =zC+5Ŕ  /-{Ŝ|q1yEe7'٪G$)SǽK1|w6e|TPGuCd&"Y1L$bw7ܹ-$]j梫:bymn1kWяÓSvw5)=i'v쑧?-G`Ѯ7yShzR9Jw*P8`IqpEJvpF٩I)b7d^sld RKO H = ZRrOՊ_/_*ԓhŠ\Ѱʻ>V?Iz8^&[XJn1ʺ2k^8PqXbtFǒW»c^;?R|jfֳcu"RqaF)FbcU9j闓Z7_|OCT|ԪG4˴*2S +mg17 РVDaBtVA(d}TS~yz(Y(Wl &cCWwÇ?~NYcS،P%>X`ip|b|x&iE[o2ڔs8T+Ͼ)>sR8/ju o$?fl'\y zTq){nԢYZM+/ ]ܷEYZOZXu HoK+ժ-od0_Pb+N4Dʗ0ʲȣЌV+Yw#Xk3̍iDOT:)=ҍuz'>WF2q^fP<Ͱljt:( 8*>%j DeN5)I"WM|0ɫuT{G)(\ ֓4iv<ӭ.4Pt]Fha( 7︱S>kw#Xh2Ɨ@~QGe]!Fg>f M5ԓɒ\CUUwX#}Q҄WSO5.(Lbn}P56VD?Q@?WLσ?GM_j 5h)zs] t8Yޘsvδ h/Jϕm#VQlv"˭ZEZ(hul˄ :֩rߚ=0oA]X5}ʲe^w"eE @6УQUoUrİ10re?!L ir[@FFwIVʃ3GMI,H'lUnc5<_͞$& q2MEƳ#d/ zVDWR*58QM7|*\YcdY̊tʌDuMZ}^gU\ DD*tVқA&xc)NnW;^H9ZhZϗHۀܶJ/%Ȏ `#;7-Gѻ[SP*- {xKHT6= -roe[\6FhX_Tl5ٟ8H>y})NqSJolmʎNcUAddz'uQ+Go?m\CcOՏ')^Al! /d7I/dG0$GV_Zօ`{1 ?jEo}GڻA`KBNQ-ZX#Ī(}psIFw*:OĂySnqטN)l)ީ33^ҠKUa3Lp:3wxU6CigWj~?hV1$EɎ]jS'ۙǛoN|qC]\`/)NjhR֤j&Æ&P2tkT_d tfmQ rTҤD8?m)H-O80|QsZTok`nfhOP$=ESouH./e;]BaP3+:TdlIMi E8?*{J.])xsTKD#&#j]E rIžoarіVFT4|N2Mz3Rač1 k6pe֛viM^jw7vL=Kx9)Gd7 12sbUvϕu?/$' fX|0XЗ XsDօckw$C\CdXԎr3I4ޑ گ uNbsP="%##9sw^L-mGSz{خ< }@,M ܗ hR78I=@ 231_@꽜p6 H5FacvmgqpQD76bnf9i;k_IhP;X?@կϴ>#Ju#=vKPaeu\(+婹IHZ;+=7m57+9%܈tu܃h-gq ޗ̑E$΀`p™v*Y9hδY@|4mlRu‹q-ۨGNf#1@8s5_\xA%y`7vc ǗlH\\RqY.-#^P -E-[;tc$abCG˒g޵|,qńȷܱc.3IkD|ōX˹J#iDHO$ֱr.`{tX%iL0OxXrjGZqX^!y,0 <*rE;4&a-7Pȭ*T2}OŒNH8TSV.% r*gsYtbUh2t7._̢V {+kg,Fhk:'╶&;B>%01MB̨NāGѱ o%*)E@ E*C͆c NiH:#U?3X+^DwfZWyJQ] 89+R ڣ*]pBAڤA2`z^F9#S-gu@5QRNsxB‚螭{luSft䣹}K`JKkqJh7V H=u^ ʬX7>"xQ@WyB(<D*v>^OSa1,ެGTX1aNkq{g;TLAA;2 mZ Q\UWPpFAA&cZ)sU<š¹۾WR"ɘ PMLb_jBc$HGP7WCy ҢKH$j:a/I8!ϥ}A“Io4M$z,nD XfǙmQDL5+nqȄՁn | U׮uNcq-r*4H\g|o}~-;XMXZ{;ўa"r zA{8.-OYlӜtHɿ@XƂ^nlZ6 :]wF'F2H$z懩siXgp\(pv˴(8CTD\1~SٵMU-VsqbT*FĝOm?{;6;}&bim4bQyFِxxU^xt"-8y[Cm]"E vlwʀ pO#5Z{?hJۍpEX"r1O>7?ދB7R ,0[-{{bLm /V t@5>3P;jk~6{H,uF\{5~0Т6}XlA ΰavvQ𼚳IJWRK3$c# ^e΋yd 5/v IFq[l蝨p,SDw{y-+wu`FG5mfG؊w\x\˜c8xE^;D=/PAm"'FԌ:Tn&3xQΛ8t+HC xn i\k\AqE6==.rum ޛwo=*.GPhc%1n3>?i6Z4M4)Ǔ\ڪbҗ.bM$rW]t5"]IwY =Xn̮Zxl.$U;X˵uմ]")&rlm²$tmbND5yIJo~uc~dԩÒںY0ٻИ*ڕªdȪ2I1ڡݫ\)"{b@65nZ>U,ךXI_C.G*qújz ]ؽ] 6AE|*?O1P xn-mԙIC)RI|gVG?װq#"򡱰*v k]jI2#]*ơ@F$AFx3g[ qK_I= ݋kCW6ȧ8;=jvZú]uLcb28Ne"ϣ/ L yH՗c –ࡼiO EhkNַVlF̬F?ntTkW1*:&W9A<Gn5 y.-0C!T;R~4MTj4qYYc R\!\)kXDfG*BwQA{nROtym4/ېc rwqWٜ^:/lBD7mO^;k[dnu v#"?1P+[ lXQF~%do4C\?vIqg3 nKUf)9ZR2Gh喙{VJ%-#葪I`Uw1oYxF;'Ѯc<:4R.zdD 0GhY&\s$TPI;Y$,ތi몦E'~'VB$j@z\r\)pt\=čݱ%ul[m4">(33!]opWG~tẀDJo %]XN Id2w5}Jbhb@ IAؚOqRJrMەWg{vqܑSmo^Q jOzj먶\E}@@Cr&~4}Ү|R# C(og6\ c =ʷҬ,G7`\F@Ǽⓑl4C 5oᄍCy@Io$yy)9ٍ^;F$?uf^x葿9kW dYpk&)\'!G"~fBN0Fj:GpTu5DrvuMZ n rՙvo,Scl|5SZnvInHb(p/-h3y)cF*γ"RگEJݳ7Y(#]:W-F8^՜^U P)W7jOZ2@ 3/bOZI$ǍN2%Jqms Rƺ6Cp?F ] ~g~oh?KN κcM}x|+Υ ?}{ʢ2Ĩ(+@xU5ek&AbR}1G s+ǘ lـ%'cm:\LhYqGJeҲ-ί_R`r;~NP.ǩ9&ʋFk:PҡuǍ6'#(=MCBf䌅R'jE\K#33ĒOR钻dG ElMcW_(4WN !$L$SlT`:^fv;J3ײ|d*ɡnƪ0[X%:E!D EHpF3: T5pN~4:]Dѯu6E椂(xW.XYe+r;!Tog+I3 3uoJ5E;u{J[(BrX' csqꗋzJHT~z:ͤgnHJn_aٶŰꗲ]]Vx\'v;sϏmlo;)-Crx GL~tKG[|!otodmmǏ}g\j)wqxb ƊU$}}*7ݣڼrZ*?0#/S+J݀(ތGКǢ_mقtۧ"2Z^?NfƜ)' /y _;vQpU݅\T1_o,M5rf88ؾ+(Iy_D5N]2pJk^;3KIYb B*gC>x"5XA.cLPR}I`[{5ɹkY*eb*Fz UO{"Kss{$yk^\8'vhAڿq #xt6%rt鄌<c]w8 7E{tXEԝ>1f|. *&8HIS9}jaCn{LNﲕJpAhb\EkÝEMv g}z',c1&-V#$G#І-#JZ78u#o y$ wl@=îK,X$1(e&f$y3DՋN(/;OЩljĖͼ$p@U`V<*D yIOYv&{m/~O;U SŸ[^̻9-r[A$H3rwcQIq==Ŝ0m;D[Fi2 ogGS4~$3nbI?hRO6;.ep-,LF= k6iŬ@$~eb 0>B_b #7J4KȞ3_8 %Uj^9փiuƒSo$S''k\UNmRGs%st-5Zx,9#|m袪2Sʚ$X\eB4ONݟk<=Vv`[eq6E-!E :V Z,xo4 Rlp.;nbT 甍𨽳qZ |=ɩ] hG]%0<ɬJ,YjZ"DA}eq\HU}AgrIf>dJNI_atjOƜCY+8"iY`,ĹZ^j6P\چ%asω+4ɳY sq{V~ hvc,qY pi =w,4LiTg|C^Gj5`c_ sŶYhqe_ R]0 B"@Y= Rۘlj:hdne GΟX-2-I FX;Mt671^1=h|>Tv|#s^W&t0m F6 v2⸱bwAPfIѤ)pֱ˦ubH_5q48>R0$g]ŕ!pf߹MxF+*<+}#l]ħ=sDgsP n!2(+6o&mZ1̡*pEx{f7#Bә~ʍ Ԙwr8!V8#ֵ(ely9՛ai1P sM6[`b' ӈI\ОTѦOYB?sq?c(}hjheӔxF@Mf{1I,)go:7trzK:{I*?U &\Sǟ\6DcW6[u{VGkQRMk<ݏ֖r~3R9KJVaWD=k4 E,Pt ƐktAbCWNxrÊSr"ArbyHJ +M,c1MdZ+ݦh|'%W<$d"+@NxC[%0vsR%8;9$ORxe$[HldVW^aPסR^ҦH 3)^|jwQk|ڧ:@ߤ>DC^Σ] sDRE&XRFS8;,oHZvesDRX. f'oZ,(W$?5/q䅚Kktwq c'h:vYq ZKͨAq4,%RRJ;c…IRTn~-tFܚZ_iM&w0xv#!IFq!ٷiK_Rj-?淚B` ʠ9*L=(H%cbM]l'ƌC{ЬgTw+F*G#!,u4;Nm7M{e}1g)=]Ie|tm`9"leHs|JP줼AZ=Ϳ̣QpgWL;)<4KZM6IYn%rpF0_*t8[k*sIm" z({譏1;x;Y` jpn*)/`'hp氖Z&o6 }(_s)h:iZjOw=F]Ben37۳ _GSd-/d|3cŷ:޸DpyGZǚ5>{Զ,Ͽt^V '# vEO> bxfwϒv vF3{5D4'5 F0i'$I%Dӵ;]v[WRHSRk)cq;Nӯ5^s5#XqzΓu\ߒfxKG*O~3HK. mfT{ XE甌xu'iZ>hخ;pfGmÚ:+ ,U˒Ag5T%yh\0g@ *T?\@5dֵ^t{=>W؞KTF '9#4u[ +Eӡ( *,RN:YGh&P8p7gzzF>7IYu l ə)W}~hR*:7v{szf 3Y$eI`ASmN]5җy'Ũqm3+eNpA ⬽\jSA 42eן dt?ՇB?a'@xr˃D.ܒaG18#yˋ{?ѴյK9TysL@`ix']4o ◾Ao YB;0=F ?jLi|kI˛-My%rKs+0UBlmJ=[i5Qp&-y҈HrF#/& (M#5xbIvRLѳ fGvoq&wdXL/d ܼlbizoqݛiG)-|lg 1δ+~$u_iEKh"dxԃFpK*ź\ZOhڶi=س8;:br2X֗询/Vk[.K@zߛ\YB*jfY=sykj4_rgzݗ } jhr{G,ȣ)ˑ|suW"m}ەbƍ6E &%#ơ;gl9W=0@ ՚FWYm#dROadO#7ه[Z{M[ȲLd1#8U8;:8g?.hmm#g %<:hgJH1hFp|=:cƺuz޽(r=tQ:˜qpq]$qCƚM4mОWCVF1]T\x0i 5`9iCsss<}=)*?L쓪rpY<隊Z)&H]&`0*Izў,\p.p <)v3>wMAeWkn֐a7 dQȨ`mzfkv6UlV>{]‡*TlZvYZoj: 2@=&I FrzVߦ\G:K QM |8E{@)@1"c+ XlfyW)-I5i~#I`cB$+F8;EP.CnyK;e,jB “p'|C9eC$ۤAҭxW8Ez $sQrG.v#ᛨ B|Al8Ľ,jqُ }ԏ!j~m2k}/ICܲM+jߢ@ !=`{ rn6}܋prU Ox14$d7dSBO[.4J9Ii"Z&`7*I+پĝSCU-.@n^llqi?~~7s=MkN4 c?}Eh)?F;Ɓm|Zn.Qg8&xH5 ʆn>Mv- >{gEPNFKMzZi^B1 >?P@lvˮ(x'I{B<}ZdE//츣O_m{Y~[ pq[7juWr]4 dcnuk DuCߪJ Bܹ؟~Oh8jHst\„[ "7Zp\).w6 CLlk,}Y{˯V5EK}xPPM*qlFy9 PGw v_;C{bV#4\2e *X|k]hOԚf9#..,"_uK湔\٭İ;2@xV])r J"2.dG1 _on1lˀtӾv "s*DxFxkZߴ5~nX"H hwpinkEu0dI$uqJHtByUl<[?~5XVcBsFYT O{. b;HbmQ7ݡPoZ=f|!Zwws[9MVeTdھyf6,P7Qx#~" i٘jwvƺ~jRj6nڃE"a,qʁV n -&_V], !aOs\O(""H$򣝼7Z5%hp|[!k]p5&ldvu#+q،dUKӸ/klQOErw<1W ,;<Ѭn+l9"v9V UܫqX/Biv:'inc-Y5pr3wGbrPƭ=pÜ&ڎ& s~rYHAVb5m{[+Jlam>ffwf~-jOhvk7p_8QҚy!K5~) f9>8U4mzφu b/6T)A{jgm?ߍ3[%̱w#:֭i&Ztn'5 hnX<_BG) 7ind@OjsX>-zuky{2JlI8CG~~#3-hWM RiBi%i9?J<:`GКMm.o$-ʹWsMxqbZOJ>= s]}ܟUt_8[ӆY}6oc/+ }V.ؿf<@ǩӤ'fɓJ%w(kGdYELFO>GUNS([1ٖhu^V8?.aʧ ѡzmtPr{ۈ 7l41)/^Sh ٱO4+aph_jڭZng4s&% #/*G8$|:Q;_'hE&,wЩNVZA5o"+KI8{$~N?9=g||ݯ yu65SMX9!DdT9я|qVqDA5Gj-BZȥߘx#GKe~5n+ѸnöVp;{e#Gp.G=ԊcuJN|@8<}/e9q;Iý*|XcOʴ-r !}Et޹0356iZ1pilRe*3d $zdׂ.NN` v2vcr>}- R>4bK nivb[K6B7doڳ o`>'}E}r2|ŪvV爬q)_-藓vM6$ʹ wj*F:cjg:ݧe蚕b#sy_M}Iwx!Ne*G٧_7ϩZJȹLcA(Q5F!$Fe`}A{Qx#~">/WTY۫NHǚÈ7*rwFqJ%~ Q%Y;oU}C * e%FzeO8UऄEb~UǼ3wg1ngS)F\s(8Ǎ/ >ve?g\Eh6-z႑bF98P5iPJW9&FگzfݚZ_]VKmh=뙹p}]6wcF٦Xqhfd&vc'd<0|EeTm(^?*/_떨1د?ӬK1lS7n~'pfZOa(٨q64^xF),:ͣlf(SK*j1hqU#5:.I!"Vyk;yŬ3Od+IMJcMcS9Ctϓ@~4B֟=!Cm5m( yK>hwcĐ"Cc1L&M 9d5ΩƖ/.u@[΀ҳ.WkX*'VzŮٍbŭo,l}GJϮxv;/Gׯ彸0<ݞyUECT((}b?q_pKN*~tN8`6;~+Ja|u#!ָt2Nr+ "b>Bgg2gUE#w#0n C.\s_9A'D''C,.MҸאr͟"D-˦w Ԅk#$ia&=3LSJ{Tܮҁ'y#>$yU?:thNZslb-[/ӣDRyu ;ׅ26A鞵\8RhNP|鋞n\"˞v| Y]]Wʷ)vj_]/NogPOm ׵As%[i' #=0t2$mKdVժ.r6SwǞFys㠢:z^_}J4s;MQ $SZA^9Ann[{}SR ,Q^ȨJHǗ6~QdhdfhRJkhmT1 rǩcIܚ's;Jwb{ܟNQN j w]6=Tc,C8f?:Z[d{΢jiE:@ P&GI%umr׊:"%hp)JَGb쯃G~vHghaX8V;SsEX֚㵚;,E?/x;NGvg! TVS:)J^_Nvڇ{ڋbmy:HF߮GLէUT%dB[oCNm@FQnRn$k1AY7$K7]HsGYV#s&q{hn4o ay{dy-n^%'ҚDs$2}rcv$DF؊h7G+Z9 ۘ"y&]Ut0.ԼkZ#;iwrj7诽uq#K&QĐ>MM}rQ]x4)<Y둀_—{cRQZ8,׹%F?ejǦF U{r0a7&<Ҁقfz$5%&`,H,-b#F Oz?3ii.d֬`+rzصVTlVsJӯYn(Pyl>֕Go4 ixJDR۰ӣmΣMH5x*givWIqmf#sd`N:kA(0;x@H«tSG"ՁmV2Z*rRhщEݴ:|x5==gB܌1#8!*ãNc~135F[jʾek1Uf AkJ$3ot֕tbN@$?T^.mmTyf^f<c$Ϋ~?*q5Kr #W* @lU)SI,={( 73J:\~ë@[}*l hV[kGRŖd!Sȩ ǿӞ[.]Pi(&4ep>eT\Uu&Kd*\QD,Jhm-ƹ@I8OK=Bl3yhՖ Ġ+G5dB(6!}y܄e_r75ZȥYוсS6t]=TKc $4G˻c6ˤ5wS;>&s:jW&kVR"Gg>93Rt}&y?ac\rKZ+=Az[(@}Kҭ"Y٩^[ix:{ʙ|cDi3tmڗ&XJJeZ>tJ{q< lu(<è"XC)b?Uˈn 8P#MWK\wCAڻ+4bDm8 )&3֚w7ɉ1V&Q^6: u6mwE}WֻxB%C&$89_"s`6uwvm#>#qMΡ!F[rR/t3tL()ڐR< ڢ+kNB[9LsA)bl11zb5 R hPF_R.V@<כvL54BD%cRCYq",tzVɜҕbFWH7?ZA$6w^UR&TI91z7.I+(<:zV tWS5 ĥy|1^U2TսR_zb^ca|gjz,jskJhWџ(/'Œ;C~]F`0Tiu'WԹ|07 JIɳuH@6rf;O6@b- V}Fo^Rg6H+gʽ^d)\Yhït?AC$xWty>L@$`W<گ{#F~ d{!֣EzF'\hVCi;ֹD#^U:C<2ʿzi,Znm";R~NFu >"|ؒS U<n:ߦ}kb#{q21(e,UK7.[sĚE@tA7+-~zWd2̲Y `3k^0# "(.A gV;=s^UTŨ]Z0Qc 9zb72,Nʒ4ۙyyyr[ϭzBi!DcdNBsu3Zh\T2rl98s+WHcorebird-1.1/examples/mm_widget.vala000066400000000000000000000015621260276623600176210ustar00rootroot00000000000000 void main (string[] args) { Gtk.init (ref args); var window = new Gtk.Window (); var widget = new MultiMediaWidget (3); //try { //var m1 = new Media (); //m1.path = "examples/media1.jpg"; //m1.loaded = true; //m1.thumbnail = new Gdk.Pixbuf.from_file ("examples/media1.jpg"); //widget.set_media (0, m1); //var m2 = new Media (); //m2.path = "examples/media2.jpg"; //m2.loaded = true; //m2.thumbnail = new Gdk.Pixbuf.from_file ("examples/media2.jpg"); //widget.set_media (1, m2); //var m3 = new Media (); //m3.path = "examples/media3.jpg"; //m3.loaded = true; //m3.thumbnail = new Gdk.Pixbuf.from_file ("examples/media3.jpg"); //widget.set_media (2, m3); //} catch (GLib.Error e) { //critical (e.message); //} window.add (widget); window.resize (500, 500); window.show_all (); Gtk.main (); } corebird-1.1/examples/tle.vala000066400000000000000000000447321260276623600164370ustar00rootroot00000000000000// {{{ const string TD1 = """ { "created_at" : "Mon May 05 06:48:32 +0000 2014", "id" : 463208606784311296, "id_str" : "463208606784311296", "text" : "RT @BlackForestTeam: DIESELSTORMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e", "source" : "web", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 62574927, "id_str" : "62574927", "name" : "Frozenbyte", "screen_name" : "Frozenbyte", "location" : "Helsinki, Finland", "description" : "We're an independent game developer. Follow us on Twitter to get the latest news on our games! For support issues please get in touch via email.", "url" : "http://t.co/NlgW9k9ZXj", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/NlgW9k9ZXj", "expanded_url" : "http://www.frozenbyte.com", "display_url" : "frozenbyte.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 5682, "friends_count" : 137, "listed_count" : 242, "created_at" : "Mon Aug 03 17:52:07 +0000 2009", "favourites_count" : 233, "utc_offset" : 10800, "time_zone" : "Helsinki", "geo_enabled" : false, "verified" : false, "statuses_count" : 1042, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "000000", "profile_background_image_url" : "http://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_image_url_https" : "https://pbs.twimg.com/profile_background_images/378800000117103508/abe5a14a1f3b0b78e9038e73bf6b812d.jpeg", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/1130292729/fb_newlogo_black480_normal.png", "profile_link_color" : "CBA051", "profile_sidebar_border_color" : "000000", "profile_sidebar_fill_color" : "D4802D", "profile_text_color" : "4A2500", "profile_use_background_image" : true, "default_profile" : false, "default_profile_image" : false, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweeted_status" : { "created_at" : "Tue Apr 29 11:00:25 +0000 2014", "id" : 461097667775725569, "id_str" : "461097667775725569", "text" : "DIESELSTORMERS Kickstarter is live! - Go and check it out right now!... http://t.co/ZVmefc0w5e", "source" : "Tumblr", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 726763934, "id_str" : "726763934", "name" : "Black Forest Games", "screen_name" : "BlackForestTeam", "location" : "Offenburg", "description" : "South-german team that brought you Giana Sisters: Twisted Dreams", "url" : "http://t.co/BXuCnqlX50", "entities" : { "url" : { "urls" : [ { "url" : "http://t.co/BXuCnqlX50", "expanded_url" : "http://gianasisterstwisteddreams.com", "display_url" : "gianasisterstwisteddreams.com", "indices" : [ 0, 22 ] } ] }, "description" : { "urls" : [ ] } }, "protected" : false, "followers_count" : 1145, "friends_count" : 308, "listed_count" : 35, "created_at" : "Mon Jul 30 20:11:50 +0000 2012", "favourites_count" : 116, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 1475, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_image_url_https" : "https://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "profile_banner_url" : "https://pbs.twimg.com/profile_banners/726763934/1369154494", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : false, "following" : false, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 6, "favorite_count" : 2, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 72, 94 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" }, "retweet_count" : 6, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/ZVmefc0w5e", "expanded_url" : "http://tmblr.co/ZTqD4s1ERcDZg", "display_url" : "tmblr.co/ZTqD4s1ERcDZg", "indices" : [ 93, 115 ] } ], "user_mentions" : [ { "screen_name" : "BlackForestTeam", "name" : "Black Forest Games", "id" : 726763934, "id_str" : "726763934", "indices" : [ 3, 19 ] } ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "en" } """; const string TD2 = """ { "created_at": "Tue Apr 29 00:50:10 +0000 2014", "id": 460944092554227713, "id_str": "460944092554227713", "text": "Combined. http:\/\/t.co\/fFJqqT1A4j", "source": "\u003ca href=\"http:\/\/twitter.com\/geekculturejam\" rel=\"nofollow\"\u003eCultureJam\u003c\/a\u003e", "truncated": false, "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "user": { "id": 657693, "id_str": "657693", "screen_name": "FOOBAR", "name": "Foo Bar", "profile_image_url" : "http://pbs.twimg.com/profile_images/3694489354/ed399e59260bf71b10235dcd7eb56fe5_normal.png", "verified" : false }, "geo": null, "coordinates": null, "place": null, "contributors": null, "retweet_count": 0, "favorite_count": 0, "entities": { "hashtags": [], "symbols": [], "urls": [], "user_mentions": [], "media": [] }, "extended_entities": { "media": [ { "id": 460938773744717825, "id_str": "460938773744717825", "indices": [ 10, 32 ], "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVX2BCEAEx4MK.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo", "sizes": { "medium": { "w": 599, "h": 397, "resize": "fit" }, "thumb": { "w": 150, "h": 150, "resize": "crop" }, "small": { "w": 340, "h": 225, "resize": "fit" }, "large": { "w": 1023, "h": 678, "resize": "fit" } } }, { "id": 460938635315916, "indices": [ 10, 32 ], "media_url": "http:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "media_url_https": "https:\/\/pbs.twimg.com\/media\/BmWVPyVCMAAeAwI.jpg", "url": "http:\/\/t.co\/fFJqqT1A4j", "display_url": "pic.twitter.com\/fFJqqT1A4j", "expanded_url": "http:\/\/twitter.com\/froginthevalley\/status\/460944092554227713\/photo\/1", "type": "photo", "sizes": { "medium": { "w": 600, "h": 600, "resize": "fit" }, "thumb": { "w": 150, "h": 150, "resize": "crop" }, "large": { "w": 1024, "h": 1024, "resize": "fit" }, "small": { "w": 340, "h": 340, "resize": "fit" } } } ] }, "favorited": false, "retweeted": false, "possibly_sensitive": false, "lang": "en" } """; const string TD3 = """ { "created_at" : "Thu Jun 12 19:34:16 +0000 2014", "id" : 477172048427765760, "id_str" : "477172048427765760", "text" : "http://t.co/ZGX7b9YGiU http://t.co/6hfxg0TPyt", "source" : "Twitter Web Client", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 993713617, "id_str" : "993713617", "name" : "Core Bird", "screen_name" : "corebirdgtk", "location" : "", "description" : "", "url" : null, "entities" : { "description" : { "urls" : [ ] } }, "protected" : true, "followers_count" : 1, "friends_count" : 6, "listed_count" : 0, "created_at" : "Thu Dec 06 19:47:16 +0000 2012", "favourites_count" : 12, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 537, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_image_url_https" : "https://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : true, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 0, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/6hfxg0TPyt", "expanded_url" : "http://i.imgur.com/xqmzPar.gif", "display_url" : "i.imgur.com/xqmzPar.gif", "indices" : [ 23, 45 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "und" } """; const string TD4 = """ { "created_at" : "Fri Jun 13 12:07:41 +0000 2014", "id" : 477422052258111488, "id_str" : "477422052258111488", "text" : "http://t.co/1zRGBKzM77 http://t.co/Dl9OXvwx6q", "source" : "Twitter Web Client", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 993713617, "id_str" : "993713617", "name" : "Core Bird", "screen_name" : "corebirdgtk", "location" : "", "description" : "", "url" : null, "entities" : { "description" : { "urls" : [ ] } }, "protected" : true, "followers_count" : 1, "friends_count" : 6, "listed_count" : 0, "created_at" : "Thu Dec 06 19:47:16 +0000 2012", "favourites_count" : 12, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 538, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_image_url_https" : "https://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : true, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 0, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "http://t.co/1zRGBKzM77", "expanded_url" : "http://instagram.com/p/pLi6v4NQ_s/", "display_url" : "instagram.com/p/pLi6v4NQ_s/", "indices" : [ 0, 22 ] }, { "url" : "http://t.co/Dl9OXvwx6q", "expanded_url" : "http://instagram.com/p/pLcyW1tQ61/", "display_url" : "instagram.com/p/pLcyW1tQ61/", "indices" : [ 23, 45 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "und" } """; const string TD5 = """ { "created_at" : "Sat Jun 14 12:15:18 +0000 2014", "id" : 477786356329234433, "id_str" : "477786356329234433", "text" : "OMG! https://t.co/OOwbJTApub", "source" : "Twitter Web Client", "truncated" : false, "in_reply_to_status_id" : null, "in_reply_to_status_id_str" : null, "in_reply_to_user_id" : null, "in_reply_to_user_id_str" : null, "in_reply_to_screen_name" : null, "user" : { "id" : 993713617, "id_str" : "993713617", "name" : "Core Bird", "screen_name" : "corebirdgtk", "location" : "", "description" : "", "url" : null, "entities" : { "description" : { "urls" : [ ] } }, "protected" : true, "followers_count" : 1, "friends_count" : 5, "listed_count" : 0, "created_at" : "Thu Dec 06 19:47:16 +0000 2012", "favourites_count" : 12, "utc_offset" : 7200, "time_zone" : "Amsterdam", "geo_enabled" : false, "verified" : false, "statuses_count" : 540, "lang" : "en", "contributors_enabled" : false, "is_translator" : false, "is_translation_enabled" : false, "profile_background_color" : "C0DEED", "profile_background_image_url" : "http://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_image_url_https" : "https://abs.twimg.com/images/themes/theme1/bg.png", "profile_background_tile" : false, "profile_image_url" : "http://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_image_url_https" : "https://abs.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", "profile_link_color" : "0084B4", "profile_sidebar_border_color" : "C0DEED", "profile_sidebar_fill_color" : "DDEEF6", "profile_text_color" : "333333", "profile_use_background_image" : true, "default_profile" : true, "default_profile_image" : true, "following" : true, "follow_request_sent" : false, "notifications" : false }, "geo" : null, "coordinates" : null, "place" : null, "contributors" : null, "retweet_count" : 0, "favorite_count" : 0, "entities" : { "hashtags" : [ ], "symbols" : [ ], "urls" : [ { "url" : "https://t.co/OOwbJTApub", "expanded_url" : "https://vine.co/v/MjVgq596Bgb", "display_url" : "vine.co/v/MjVgq596Bgb", "indices" : [ 5, 28 ] } ], "user_mentions" : [ ] }, "favorited" : false, "retweeted" : false, "possibly_sensitive" : false, "lang" : "und" } """; // """ // }}} void main (string[] args) { Settings.init (); Twitter.get ().init (); var account = new Account (1234, "foobar", "Foo Bar"); var now = new GLib.DateTime.now_local (); var parser = new Json.Parser (); try { parser.load_from_data (TD3); } catch (GLib.Error e) { critical (e.message); } var root_node = parser.get_root (); Tweet tweet = new Tweet (); tweet.load_from_json (root_node, now, account); Gtk.init (ref args); Utils.load_custom_css (); Utils.load_custom_icons (); var list = new Gtk.ListBox (); list.selection_mode = Gtk.SelectionMode.NONE; var window = new Gtk.Window (); window.add (list); var entry = new TweetListEntry (tweet, null, account); list.add (entry); window.show_all (); Gtk.main (); } corebird-1.1/po/000077500000000000000000000000001260276623600135745ustar00rootroot00000000000000corebird-1.1/po/.gitignore000066400000000000000000000001041260276623600155570ustar00rootroot00000000000000_*.pot *.gmo stamp-it Makefile.in.in .intltool-merge-cache POTFILES corebird-1.1/po/LINGUAS000066400000000000000000000001301260276623600146130ustar00rootroot00000000000000ar ast ca ca@valencia de en_AU es es_VE fa fi fr hu id_ID it ja lt nl pl pt_BR ru zh_CN corebird-1.1/po/POTFILES.in000066400000000000000000000035451260276623600153600ustar00rootroot00000000000000src/window/ComposeTweetWindow.vala src/window/UserListDialog.vala src/window/ModifyFilterDialog.vala src/widgets/TweetListBox.vala src/widgets/AccountCreateWidget.vala src/widgets/PixbufButton.vala src/widgets/MultiMediaWidget.vala src/widgets/AddImageButton.vala src/widgets/FollowButton.vala src/HomeTimeline.vala src/DMThreadsPage.vala src/resources.c src/list/DMThreadEntry.vala src/ListsPage.vala src/ProfilePage.vala src/TweetInfoPage.vala src/util/Utils.vala src/SearchPage.vala src/Corebird.vala src/MentionsTimeline.vala src/FavoritesTimeline.vala src/DMPage.vala src/ListStatusesPage.vala src/widgets/AvatarBannerWidget.vala src/window/ImageCropDialog.vala src/window/SettingsDialog.vala [type: gettext/glade]ui/settings-dialog.ui [type: gettext/glade]ui/menu.ui [type: gettext/glade]ui/user-lists-widget.ui [type: gettext/glade]ui/about-dialog.ui [type: gettext/glade]ui/dm-page.ui [type: gettext/glade]ui/load-more-entry.ui [type: gettext/glade]ui/tweet-list-entry.ui [type: gettext/glade]ui/user-list-entry.ui [type: gettext/glade]ui/new-list-entry.ui [type: gettext/glade]ui/search-page.ui [type: gettext/glade]ui/compose-window.ui [type: gettext/glade]ui/profile-page.ui [type: gettext/glade]ui/main-window.ui [type: gettext/glade]ui/account-create-widget.ui [type: gettext/glade]ui/tweet-info-page.ui [type: gettext/glade]ui/list-list-entry.ui [type: gettext/glade]ui/start-conversation-entry.ui [type: gettext/glade]ui/list-statuses-page.ui [type: gettext/glade]ui/filter-list-entry.ui [type: gettext/glade]ui/filter-page.ui [type: gettext/glade]ui/modify-filter-dialog.ui [type: gettext/glade]ui/user-filter-entry.ui [type: gettext/glade]ui/account-dialog.ui [type: gettext/glade]ui/image-crop-dialog.ui [type: gettext/glade]ui/modify-snippet-dialog.ui data/org.baedert.corebird.appdata.xml.in data/org.baedert.corebird.gschema.xml.in data/org.baedert.corebird.desktop.in.in corebird-1.1/po/POTFILES.skip000066400000000000000000000015371260276623600157170ustar00rootroot00000000000000src/Corebird.c src/DMThreadsPage.c src/FavoritesTimeline.c src/FilterPage.c src/HomeTimeline.c src/ListsPage.c src/MentionsTimeline.c src/ProfilePage.c src/SearchPage.c src/TweetInfoPage.c src/list/DMThreadEntry.c src/list/ProgressEntry.c src/list/TweetListEntry.c src/util/Utils.c src/DMPage.c src/ListStatusesPage.c src/MainWindow.c src/ITimeline.c src/widgets/AccountCreateWidget.c src/widgets/TweetListBox.c src/widgets/PixbufButton.c src/widgets/MultiMediaWidget.c src/widgets/MediaImageWidget.c src/widgets/AddImageButton.c src/widgets/FollowButton.c src/window/ComposeTweetWindow.c src/window/ImageDialog.c src/window/UserListDialog.c src/window/ModifyFilterDialog.c src/widgets/AvatarBannerWidget.c src/window/ImageCropDialog.c src/window/ModifySnippetDialog.c src/window/SettingsDialog.c src/model/NotificationItem.c data/org.baedert.corebird.desktop.in corebird-1.1/po/ar.po000066400000000000000000000367121260276623600145470ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Med Touhami MAHDI , 2014 # Med Touhami MAHDI , 2014 # Med Touhami MAHDI , 2014 # Med Touhami MAHDI , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Arabic (http://www.transifex.com/corebird/corebird/language/" "ar/)\n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "إختيار صورة" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "إلغاء" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "اختيار" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "حفظ" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "يوافق" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "لا يطابق" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "لم يتم العثور على أي شيء" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "غير مسموح. غالبا هذا يعني أن هناك خطأ ما في خوادم تويتر. المرجو المحاولة " "لاحقا." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "قن خاطئ" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "نسخ الرابط" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "نسخ الرابط" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "حفظ الأصلي" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "فتح في المتصفح." #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "حفظ الصورة" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "تَتبٌع" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "إلغاء التتبُع" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s أعاد تغريد %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s غرد" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" msgstr[4] "" msgstr[5] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "الرئيسية" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" msgstr[4] "" msgstr[5] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "رسالة مباشرة جديدة من %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "رسائل مباشرة" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" msgstr[4] "" msgstr[5] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "قواءم" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "ملف محمي" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "غرد لِ@%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "إعادات التغريدات" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "المفضلة" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "المصدر" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "تفاصيل التغريدة" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "الآن" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dدقيقة" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dساعة" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "البحث" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "فتح الحساب" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "إشاراة جديدة من @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "الإشارات" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "محادثة مباشرة" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "قائمة" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" msgstr[4] "" msgstr[5] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" msgstr[4] "" msgstr[5] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "الإعدادات" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "الواجهة" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "العمليات" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "أبدا" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "كل" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "تجميع 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "تجميع 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "تجميع 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "تجميع 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "الإشعارات" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "تغريدات" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "حول" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "الجروج" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "تم الإنشاء" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "مشترك في" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "حول كوربرد" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "مع إستعمال Font Awesome ل Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "إرسال" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "المزيد" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "إقتباس" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "حذف" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "إنشاء قائمة جديدة" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "الإسم" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "إنشاء" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "المستخدمين" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "كتابة تغريدة" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "كتابت رسالة مباشرة" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "الإضافة أو الحذف من القائمة" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "محضور" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "يتَتبعك" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "المتتبعون" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "يتتبع" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "تغريدة جديدة" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "القن" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "تأكيد" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "إعادت التغريد" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "تفضيل التغريدة" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "الرد على التغريدات" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "المزيد" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "الإشتراك" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "إلغاء الإشتراك" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "بدأ محادثة جديدة" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "مع" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "التحدث" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "المشتركين" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "الأعضاء" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "المنشئ" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "أنشئ في" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "تعديل" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "الوضع" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "خاص" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "عمومي" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "كوربرد عميل تويتر GTK+ أصلي يتوفر على ميزات حيوية مثل الرسائل المباشرة " "والإخطار بالتغردات ووِجهات المحادثة." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "عامل تويتر" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/ast.po000066400000000000000000000376331260276623600147370ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # enolp , 2014-2015 # Ḷḷumex03 , 2014 # Xuacu Saturio , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Asturian (http://www.transifex.com/corebird/corebird/language/" "ast/)\n" "Language: ast\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Esbillar imaxe" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Encaboxar" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Escoyer" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Amestar o desaniciar usuariu de la llista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Guardar" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Nun tienes llistes." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modificar filtru" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Coincidencies" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Nun concasa" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Nun s'alcontraron entraes" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Reintentar" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "¿Entá nun tienes una cuenta?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Crea una" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Non autorizáu. La mayoría de vegaes pue significar qu'hai daqué mal colos " "sirvidores de Twitter y deberíes intentalo de nueves sero" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Nun pudo abrise %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN incorreutu" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "La cuenta yá ta n'usu" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copiar enllaz" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copiar URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Guardar orixinal" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Abrir nel restolador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Guardar imaxe" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Primi pa desaniciar la imaxe" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Primi p'amestar la imaxe" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Siguir" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Dexar de siguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retuiteó %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tuiteó" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "¡%d tuit nuevu!" msgstr[1] "¡%d tuits nuevos!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Aniciu" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d mensaxe nuevu de %s" msgstr[1] "%d mensaxes nuevos de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Mensaxe direutu nuevu de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Mensaxes direutos" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d ensin lleer)" msgstr[1] "(%d ensin lleer)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Llistes" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Perfil protexíu" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tuitear a @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retuits" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoritos" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Fonte" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalles del tuit" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Agora" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Guetar" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Abrir cuenta" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Mención nueva de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menciones" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversación direuta" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Llista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Esbillar pancarta" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Esbillar semeya" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Siguiente" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "La imaxe nun cumple colos requirimientos de tamañu mínimos:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Anchor mínimu: %d píxel" msgstr[1] "Anchor mínimu: %d píxeles" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Altor mínimu: %d píxel" msgstr[1] "Altor mínimu: %d píxeles" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Axustes" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Tamañu de multimedia máximu" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Desplazamientu automáticu en tuits nuevos" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Activación con clic doblu" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfaz" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "En tuits nuevos" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Aiciones" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "En menciones nueves" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "En mensaxes nuevos" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Enxamás" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Cada" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Pila de 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Pila de 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Pila de 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Pila de 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificaciones" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatares arredondiaos" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Desaniciar les etiquetes del final" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Desaniciar los enllaces a multimedia" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tuits" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Tocante a" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Colar" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creáu" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Soscribise a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Tocante a Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Usando Font Awesome por Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Unviar" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Cargar más" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Citar" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Desaniciar" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favoritu" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Contestar" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Amosar los axustes d'esta cuenta" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Abrir nuna ventana nueva" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crear llista nueva" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nome:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crear" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Usuarios" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Componer tuit" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Escribir mensaxe direutu nuevu" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Amestar a/Desaniciar de la llista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloquiáu" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retuits deshabilitaos" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Síguete" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Siguidores" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Siguiendo" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Amosar cuentes configuraes" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Componer tuit" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Tuit nuevu" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Cuenta nueva" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Pidir PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirmar" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retuitear tuit" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Conseñar tuit como favoritu" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Responder al tuit" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Más" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Soscribise" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Esborrase" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Entamar conversación nueva" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Con:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Dir" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Soscriptores:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Miembros:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creáu a les:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Editar" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mou:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Priváu" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Públicu" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Amestar filtru nuevu" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Desbloquiar" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Axustes de la cuenta" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nome" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Sitiu web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Aniciu automáticu" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "¿De xuru que quies desaniciar esta cuenta?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Atrás" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird ye un veceru nativu pa Twitter en GTK+ qu'apurre carauterístiques " "vitales como mensaxes direutos (DM), notificaciones de tuits, visión de " "conversaciones." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Carauterístiques adicionales qu'inclúin visión llocal de videos, imáxenes en " "llinia múltiples, llistes, filtros, cuentes múltiples, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Vista de llinia temporal al usar Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Perfil típicu de Twitter." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Puen configurase los axustes de cuenta como'l nome, sitiu web, la " "descripción y l'avatar." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Veceru pa Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Usa Twitter dende una aplicación normal d'escritoriu" corebird-1.1/po/ca.po000066400000000000000000000373171260276623600145320ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Estanislau Trepat , 2015 # Pau Iranzo , 2014 # Sergi , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Catalan (http://www.transifex.com/corebird/corebird/language/" "ca/)\n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Selecciona una imatge" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancel·la" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Selecciona" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Afegeix o elimina un usuari de la llista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Desa" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "No tens cap llista" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modifica el filtre" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Coincideix" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "No conincideix" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "No s'ha trobat cap resultat" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Prova de nou" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Encara no teniu un compte?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Creeu-ne un" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "No s'ha autoritzat. Normalment això es produeix perquè alguna cosa no " "funciona bé als servidors del Twitter. Proveu més tard" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "No s'ha pogut obrir %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN incorrecte" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Ja s'està utilitzant el compte" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copia l'enllaç" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copia l'URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Desa l'original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Obre al navegador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Desa la imatge" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Clica per treure la imatge" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Clica per posa la imatge" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Segueix" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Deixa de seguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s ha repiulat %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s ha repiulat" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nou tweet!" msgstr[1] "%d nous tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Inici" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nou missatge de %s" msgstr[1] "%d nous missatges de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Hi ha un missatge directe nou de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Missatges directes" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d missatge no llegit)" msgstr[1] "(%d missatges no llegits)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Llistes" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Perfil protegit" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Piula a @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Repiulades" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Preferits" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Origen" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalls de la piulada" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Ara" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Cerca" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Obre un compte" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Menció nova de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Mencions" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversa directa" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Llista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Seleccioneu un bàner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Seleccioneu un avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Següent" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "La imatge no té els requisits mínims de tamany" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Amplada mínima: %d pixel" msgstr[1] "Amplada mínima: %d pixels" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Alçada mínima: %d pixel" msgstr[1] "Alçada mínima: %d pixels" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Paràmetres" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Mida màxima de fitxers multimèdia" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Desplaça automàticament amb piulades noves" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Activació de doble clic" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfície" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Quan hi hagi piulades noves" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Accions" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Quan hi hagi mencions noves" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Quan hi hagi missatges nous" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Mai" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Tots els" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Stack 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Stack 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Stack 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Stack 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificacions" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatars arredonits" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Eliminar hashtags posteriors" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Eliminar enllaços" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Piulades" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Quant a" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Surt" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creat" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Subscrit a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Quant al Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" "Fent servir el tipus de lletra Awesome per Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Envia" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Carrega'n més" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cita" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Suprimeix" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favorit" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Contesta" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostra els paràmetres per a aquest compte" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Obre a una finestra nova" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crea una llista nova" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nom:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crea" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Usuaris" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Redacteu una piulada" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Escriu un missatge directe" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Afegeix/Elimina de la llista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Blocat" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "S'han desactivat les repiulades" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Us segueix" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seguidors" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Seguint" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostra els comptes configurats" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Escriu un nou tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Piulada nova" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Compte nou" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Sol·licita un PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirma" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Repiula la piulada" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Marca com a preferit" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Respon a la piulada" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Més" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Subscriviu-vos" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Cancel·la la subscripció" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Inicia una conversa nova" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Amb:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Vés" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Subscriptors:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Membres:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creat el:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Edita" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mode:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privat" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Públic" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Afegeix un filtre nou" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Desbloqueja " #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Paràmetres del compte" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nom" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Lloc web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Inici automàtic" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Voleu eliminar aquest compte?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Enrere" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "El Corebird és un client del twitter natiu GTK+ que proveeix " "característiques bàsiques com missatges directes, notificacions de piulades " "i visualització de converses. " #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Típic perfil de twitter" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Client del Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Feu servir el Twitter des d'una aplicació d'escriptori" corebird-1.1/po/ca@valencia.po000066400000000000000000000362101260276623600163240ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Pau Iranzo , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Catalan (Valencian) (http://www.transifex.com/corebird/" "corebird/language/ca@valencia/)\n" "Language: ca@valencia\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Selecciona una imatge" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancel·la" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Selecciona" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Afig o elimina un usuari de la llista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Guarda" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modifica el filtre" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Coincideix" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "No conincideix" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "No s'ha trobat cap resultat" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Prova de nou" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Encara no teniu un compte?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Creeu-ne un" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "No s'ha autoritzat. Normalment això es produeix perquè alguna cosa no " "funciona bé als servidors del Twitter. Proveu més tard" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN incorrecte" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Ja s'està utilitzant el compte" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copia l'enllaç" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copia l'URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Guarda l'original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Obri al navegador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Guarda la imatge" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Segueix" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Deixa de seguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s ha repiulat %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s ha repiulat" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" msgstr[1] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Inici" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" msgstr[1] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Hi ha un missatge directe nou de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Missatges directes" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" msgstr[1] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Llistes" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Perfil protegit" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Piula a @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Repiulades" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Preferits" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Origen" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalls de la piulada" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Ara" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Cerca" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Obri un compte" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Menció nova de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Mencions" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversa directa" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Llista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Seleccioneu un bàner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Seleccioneu un avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Següent" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Paràmetres" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Mida màxima de fitxers multimèdia" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Desplaça automàticament amb piulades noves" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfície" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Quan hi haja piulades noves" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Accions" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Quan hi haja mencions noves" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Quan hi haja missatges nous" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Mai" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Tots els" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Stack 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Stack 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Stack 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Stack 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificacions" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Piulades" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Quant a" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Ix" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creat" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Subscrit a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Quant al Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" "Fent servir el tipus de lletra Awesome per Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Envia" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Carrega'n més" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cita" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Suprimeix" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostra els paràmetres per a este compte" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Obri a una finestra nova" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crea una llista nova" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nom:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crea" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Usuaris" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Redacteu una piulada" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Escriu un missatge directe" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Afig/Elimina de la llista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Blocat" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "S'han desactivat les repiulades" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Vos segueix" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seguidors" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Seguint" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostra els comptes configurats" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Piulada nova" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Compte nou" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Sol·licita un PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirma" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Repiula la piulada" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Marca com a preferit" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Respon a la piulada" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Més" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Subscriviu-vos" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Cancel·la la subscripció" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Inicia una conversa nova" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Amb:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Vés" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Subscriptors:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Membres:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creat el:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Edita" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mode:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privat" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Públic" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Afig un filtre nou" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Paràmetres del compte" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nom" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Lloc web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Inici automàtic" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Voleu eliminar este compte?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Arrere" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "El Corebird és un client del twitter natiu GTK+ que proveeix " "característiques bàsiques com missatges directes, notificacions de piulades " "i visualització de converses. " #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Client del Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Feu servir el Twitter des d'una aplicació d'escriptori" corebird-1.1/po/corebird.pot000066400000000000000000000321001260276623600161050ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" msgstr[1] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" msgstr[1] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" msgstr[1] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/de.po000066400000000000000000000406661260276623600145400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # fgreinus , 2015 # jupaja , 2014-2015 # baedert , 2014-2015 # Michael , 2014 # Philip Gillißen , 2015 # Richard Schwab , 2014 # encbladexp , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-21 16:45+0000\n" "Last-Translator: Philip Gillißen \n" "Language-Team: German (http://www.transifex.com/corebird/corebird/language/" "de/)\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Zitiere Tweet" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Bild auswählen" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Abbrechen" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Auswählen" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Nutzer zu Liste hinzufügen oder entfernen" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Speichern" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Du hast keine Listen." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Filter ändern" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Passt" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Passt nicht" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Laden..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Keine Einträge gefunden" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Erneut versuchen" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Noch keinen Account?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Erstelle einen" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Unautorisiert. Meinstens bedeutet dies dass es ein Problem mit den Twitter " "servern gibt und es später erneut versucht werden sollte." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Konnte %s nicht öffnen" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Falsche PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Account schon in Benutzung" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Kopiere Link" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Kopiere URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Speichere Original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Im Browser öffnen" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Bild speichern" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Klicke um das Bild zu löschen" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Klicke um ein Bild hinzuzufügen" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Folgen" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Entfolgen" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweetete %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tweetete" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d neuer Tweet!" msgstr[1] "%d neue Tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Timeline" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d neue Nachricht von %s" msgstr[1] "%d neue Nachrichten von %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Neue Direktnachricht von %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Direktnachrichten" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d ungelesen)" msgstr[1] "(%d ungelesene)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listen" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Geschütztes Profil" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet an @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Konnte Tweet nicht anzeigen" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoriten" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Quelle" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Tweet Details" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Jetzt" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dM" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dS" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Suchen" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Account öffnen" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Neue Erwähnung von @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Erwähnungen" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Direcktnachrichten" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Liste" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Banner auswählen" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Avatar auswählen" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Weiter" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Bild entspricht nicht der mindest Größe:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Minimum Breite sind %d Bildpunkte" msgstr[1] "Minimum Breite sind %d Bildpunkten" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Minimum Höhne sind %d Bildpunkte" msgstr[1] "Minimum Höhne sind %d Bildpunkten" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Hey, schau dir die neue #Corebird version an! \\ (•◡•) / #cool " "#newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Einstellungen" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Maximale Bildergröße" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Automatisch scrollen bei neuen Tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Aktivieren per Doppelklick" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Oberfläche" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Bei neuen Tweets" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Aktionen" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Bei Neuen Erwähnungen" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Bei neuen Nachrichten" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Niemals" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Jeder" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Sammle 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Sammle 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Sammle 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Sammle 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Benachrichtigungen" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Runde Avatare" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Entferne nachfolgende Hashtags" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Entferne Medienverweise" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Keine Schnipsel eingerichtet" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "Du kannst Schnipsel auswählen, in dem du das Stichwort tippst und dann " "Tabulator drückst" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Schnipsel" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Über" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Beenden" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Erstellt" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Anmelden zu" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Über Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Benutzt die Schrift Awesome von Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Senden" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Mehr laden" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Zitieren" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Löschen" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favoriten" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Antworten" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Zeige die Einstellungen dieses Accounts" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "In neuem Fenster öffnen" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Neue Liste erstellen" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Name:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Erstellen" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Benutzer" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Tweet erstellen" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Direktnachricht schreiben" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Hinzufügen / Entfernen aus der Liste" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Blockiert" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets deaktiviert" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Folgt dir" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Followers" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Folgt" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Zeige konfigurierte Accounts" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Verfasse ein Tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Neuer Tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Neuer Account" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "PIN anfordern" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Bestätigen" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Tweet retweeten" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Favorisieren" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Auf Tweet antworten" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Mehr" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Abonnieren" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Abbestellen" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Neue Unterhaltung beginnen" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Mit:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Los" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Abonnenten" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Mitglieder:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Ersteller:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Erstellt um:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Bearbeiten" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modus:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privat" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Öffentlich" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Neuen Filter Hinzufügen" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Entsperren" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Account Einstellungen" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Name" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Webseite" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Autostart" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Willst Du diesen Account wirklich löschen?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Zurück" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Neuen Schnipsel anlegen" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Stichwort" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Ersetzung" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird ist ein nativer GTK+ Twitter-Client, der wesentliche Funktionen wie " "Direktnachrichten (DMs), Tweet-Benachrichtigungen und Konversationen bietet." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Weitere Funktionalitäten beinhalten die lokale Anzeige von Videos, mehrere " "eingebettete Bilder, Listen, Filter, mehrere Accounts, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Übergeordnete Zeitleistenansicht bei der Nutzung von Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Typisches Twitter-Profil" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Account-Einstellungen wie der Name, die Webseite, die Beschreibung und der " "Avatar können konfiguriert werden." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter Client" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Nutzen Sie Twitter in einer normalen Desktopanwendung" corebird-1.1/po/en_AU.po000066400000000000000000000337321260276623600151330ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Ryan Lerch , 2014 # Ryan Lerch , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: English (Australia) (http://www.transifex.com/corebird/" "corebird/language/en_AU/)\n" "Language: en_AU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Select Image" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancel" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Choose" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Save" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "No entries found" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Unauthorised. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Wrong PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Open in Browser" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Save image" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Follow" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Unfollow" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweeted %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tweeted" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" msgstr[1] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Home" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" msgstr[1] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Direct Messages" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" msgstr[1] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Lists" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Protected profile" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet to @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favourites" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Source" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Now" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Search" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Open Account" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Mentions" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" msgstr[1] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Settings" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Actions" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Never" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Every" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Stack 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Stack 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Stack 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Stack 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "About" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Quit" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Created" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Subscribed to" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "About Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Using Font Awesome by Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Send" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Load more" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Quote" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Delete" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Create New List" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Name:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Create" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Users" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Compose Tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Write Direct Message" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Add to/Remove from List" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Follows you" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "New tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirm" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retweet tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Favorite tweet" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Reply to tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "More" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Subscribe" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Unsubscribe" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Start new conversation" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "With:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Go" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Subscribers:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Members:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creator:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Created at:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Edit" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mode:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Private" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Public" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/es.po000066400000000000000000000403351260276623600145500ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # auroszx , 2014 # Carlos C Soto , 2015 # Jose Gregorio Jimenez Sanchez , 2014-2015 # Jose Manuel Calero Gonzalez , 2014-2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Spanish (http://www.transifex.com/corebird/corebird/language/" "es/)\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Citar tweet" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Seleccionar Imagen" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancelar" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Elegir" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Agregar o Quitar usuario desde la lista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Guardar" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "No tiene listas." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modificar Filtro" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Concuerda" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "No concuerda" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Cargando..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "No se han encontrado entradas" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Reintentar" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "¿Aún no tienes una cuenta?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Crear una" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Sin autorización. La mayoría de las veces, esto significa que hay un " "problema con los servidores de Twitter y debes volver a intentarlo más tarde." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "No se puede abrir %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN incorrecto" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "La cuenta ya está en uso" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copiar enlace" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copiar URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Guardar original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Abrir en navegador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Guardar imagen" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Click para eliminar imagen" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Click para agregar una imagen" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Seguir" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Dejar de seguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retuiteado %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tuiteado" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nuevo Tweet!" msgstr[1] "%d nuevos Tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Inicio" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nuevo mensaje de %s" msgstr[1] "%d nuevos mensajes de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nuevo mensaje directo de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Mensajes directos" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d sin leer)" msgstr[1] "(%d sin leer)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listas" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "perfil protegido" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet para @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoritos" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Fuente" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalles del tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Ahora" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Buscar" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Abrir Cuenta" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nueva mención de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menciones" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversación directa" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Seleccionar banner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Seleccionar avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Siguiente" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Imagen no cumple los requisitos mínimos de tamaño:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Ancho mínimo: %d pixel" msgstr[1] "Ancho mínimo: %d píxeles" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Altura mínima: %d pixel" msgstr[1] "Altura mínima: %d píxeles" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "¡Ey, revisa esta nueva versión de #Codebird! \\ (•◡•) / #cool " "#newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Preferencias" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Tamaño máximo de imágenes" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Desplazar automaticamente al cargar nuevos tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Activación Doble-click" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfaz" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Para tweets nuevos" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Acciones" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Para menciones nuevas" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Para mensajes nuevos" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Nunca" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Todos" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Cada 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Cada 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Cada 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Cada 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificaciones" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatares Redondeados" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Eliminar hashtags posteriores" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Eliminar enlaces" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "No hay fragmentos configurados" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "Puedes activar los fragmentos escribiendo la clave y presionando TAB" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Fragmentos" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Acerca de" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Salir" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creada" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Suscrito a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Sobre Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Usando Fuente Awesome de Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Enviar" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Cargar más" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Citar" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Eliminar" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favorito" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Responder" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostrar ajustes de la cuenta" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Abrir en una nueva ventana" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crear lista nueva" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nombre:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crear" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Usuarios" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Escribir Tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Enviar mensaje directo" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Añadir/Eliminar de la lista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloqueado" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets desactivados" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Te sigue" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seguidores" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Siguiendo" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostrar cuentas configuradas" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Redactar tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nuevo tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nueva cuenta" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Solicitar PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirmar" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Hacer retweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Añadir a favoritos" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Responder" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Mas" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Suscribirse" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Anular suscripción" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Iniciar conversación nueva" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Con:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Ir" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Suscriptores:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Miembros:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creada el:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Editar" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modo:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privado" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Público" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Añadir nuevo filtro" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Desbloqueo" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Configuración de cuentas" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nombre" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Página Web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Autoiniciar" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "¿Seguro que quieres eliminar esta cuenta?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Atrás" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Añadir nuevo fragmento" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Clave" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Reemplazo" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird es un cliente nativo GTK+ para Twitter que provee funciones útiles " "como Mensajes Directos (DMs), notificación de tweets, y ver conversaciones." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Las características adicionales incluyen la visualización local de los " "vídeos, múltiples imágenes en línea, listas, filtros, múltiples cuentas, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Vista cronológica genérica al utilizar Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Típico perfil de Twitter " #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Configuración de la cuenta, como Nombre, Sitio Web, Descripción y Avatar se " "pueden configurar." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Cliente Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Usa Twitter desde una aplicación de escritorio común" corebird-1.1/po/es_VE.po000066400000000000000000000403241260276623600151400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Jerry Anselmi , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-13 02:49+0000\n" "Last-Translator: Jerry Anselmi \n" "Language-Team: Spanish (Venezuela) (http://www.transifex.com/corebird/" "corebird/language/es_VE/)\n" "Language: es_VE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Cita de tweet" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Seleccione una imagen" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancelar" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Escoger" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Agregar o eliminar usuario de la lista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Guardar" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "No tienes listas." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modificar filtro" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Coincidencias" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "No hay coincidencias" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Cargando..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "No se encontraron entradas" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Reintentar" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "¿No tienes una cuenta todavía?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Crear una" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "No autorizado. La mayoría de las veces, esto significa que hay algo mal con " "los servidores de Twitter y usted debe intentarlo más tarde" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "No se pudo abrir %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN incorrecto" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "La cuenta ya esta siendo usada" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copiar enlace" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copiar URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Guardar original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Abrir en un navegador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Guardar imagen" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Haga clic para eliminar la imagen" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Haga clic para agregar la imagen" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Seguir" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Dejar de seguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweeteado %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tweeteado" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nuevo Tweet!" msgstr[1] "%d nuevos Tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Inicio" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nuevo Mensaje de %s" msgstr[1] "%d nuevos Mensajes de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nuevo mensaje directo de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Mensajes directos" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d sin leer)" msgstr[1] "(%d sin leer)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listas" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Perfil protegido" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet a @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "No se pudo mostrar el tweet" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoritos" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Fuente" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalles del tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Ahora" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Buscar" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Abrir una cuenta" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nueva Mención de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menciones" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversación directa" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Seleccione el banner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Seleccione el avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Siguiente" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "La imagen no tiene el tamaño mínimos requerido:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Ancho minimo: %d pixel" msgstr[1] "Ancho minimo: %d pixels" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Alto mínimo: %d pixel" msgstr[1] "Alto mínimo: %d pixels" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Hey, echa un vistazo a esta nueva versión #Corebird! \\ (• ◡ •) / #cool " "#newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Ajustes" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Tamaño maximo para imagen, video y audio" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Desplazamiento automático con nuevos tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Activación con doble clic" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfaz" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "En nuevos Tweets" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Acciones" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "En nuevas menciones" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "En nuevos mensajes" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Nunca" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Cada" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Grupo de 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Grupo de 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Grupo de 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Grupo de 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificaciones" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Redondear aavaataares" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Eliminar trailing hashtags" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Eliminar enlaces de imagenes, videos y audios" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "trailing hashtags" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "No hay fragmentos configurados." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "Puede activar fragmentos escribiendo la palabra clave y presionar TAB." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Fragmento" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Acerca de" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Salir" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creado" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Suscrito a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Acerca de Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Usando Font Awesome de Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Enviar" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Cargar mas" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cita" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Borrar" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favorito" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Responder" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostrar los ajustes de esta cuenta" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Abrir en una nueva ventana" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crear una nueva lista" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nombre:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crear" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "usuarios" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Hacer un Tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Escribir un mensaje directo" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Agregar/Eliminar de la lista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloqueado" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets desabilitado" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Le sigue" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seguidores" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Siguiendo" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostrar cuentas configuradas" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Hacer un tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nuevo tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nueva cuenta" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Solicitud de PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirmar" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retweet tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Tweet favorito" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Responder tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Más" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Suscribirse" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Darse de baja" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Iniciar una nueva conversación" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Con:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Ir" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Suscriptores:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Miembros:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creado en:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Editar" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modo:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privado" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Publico" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Agregar un nuevo filtro" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Desbloquear" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Configuraciones de la cuenta" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nombre" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Sitio Web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "inicio automatico" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "¿Estas seguro de que quieres eliminar esta cuenta?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Volver" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Agregar un nuevo fragmento" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Palabra clave" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Reemplazo" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird es un cliente nativo GTK+ de Twitter que proporciona funciones " "vitales tales como mensajes directos (DM), notificaciones, vistas de " "conversación." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Las características adicionales incluyen la visión local de los vídeos, " "múltiples imágenes en línea, listas, filtros, múltiples cuentas, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Timeline genérico cuando usas Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Perfil típico de Twitter." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Los ajustes de la cuenta tales como Nombre, Descripción y avatar son " "configurables " #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Cliente de Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Utilice a Twitter desde una aplicación de escritorio" corebird-1.1/po/fa.po000066400000000000000000000350411260276623600145250ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # amraei , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Persian (http://www.transifex.com/corebird/corebird/language/" "fa/)\n" "Language: fa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "انتخاب تصویر" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "انصراف" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "انتخاب" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "ذخیره سازی" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "مطابقت داره" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "مطابقت نداره" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "چیزی یافت نشد!" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "غیر مجاز. اغلب این به معناست که توی ارتباط با سرور توییتر یه اشکالی هست و " "بهتره یه وقت دیگه دوباره امتحان کنید." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN اشتباهه" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "توی مرورگر باز بشه" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "ذخیره سازی عکس" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "دنبال کردن" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "دنبال نکنید" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s توییت شد" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "خانه" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "پیام مستقیم" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "لیست ها" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "پروفایل محافظت شده" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "توییت های مجدد" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "علاقه مندی ها" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "منبع" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "اکنون" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "جستجو" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "بازکردن حساب" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "اشاره ها" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "تنظیمات" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "رابط کاربری" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "هرگز" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "هرکسی" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "اعلان ها" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "توییت ها" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "درباره" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "خروج" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "ایجاد شد" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "مشترک شد" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "درباره Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" "از فونت های Font Awesome که توسط Dave Gandy طراحی شدند استفاده کن - http://" "fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "ارسال کن" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "بیشتر" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "نقل قول" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "حذف" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "یه لیست جدید ایجاد کنید" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "نام" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "ایجاد کنید" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "کاربران" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "توییت کنید" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "یه پیام مستقیم بنویسید" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "اضافه کردن به/ حذف از لیست" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "بلاک شده" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "شمال رو دنبال می کنه" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "توییت جدید" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "تایید" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "بازنشر توییت" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "توییت های مورد علاقه" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "پاسخ به توییت" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "بیشتر" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "مشترک شو" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "لغو اشتراک" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "همراه با:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "برو" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "مشترکین:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "اعضا:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "ایجاد کننده" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "ایجاد شده در:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "ویرایش" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "حالت:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "خصوصی" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "عمومی" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/fi.po000066400000000000000000000402771260276623600145440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Jiri Grönroos , 2014-2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 10:33+0000\n" "Last-Translator: Jiri Grönroos \n" "Language-Team: Finnish (http://www.transifex.com/corebird/corebird/language/" "fi/)\n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Lainaa twiittiä" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Valitse kuva" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Peru" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Valitse" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Lisää tai poista käyttäjä listalta" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Tallenna" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Sinulla ei ole listoja." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Muokkaa suodatinta" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Vastaa" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Ei vastaa" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Ladataan..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Kohteita ei löytynyt" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Yritä uudelleen" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Oletko vailla tiliä?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Luo uusi tili" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Ei valtuutusta. Yleensä tämä tarkoittaa, että jotain on vialla Twitter-" "palvelimien kanssa, joten yritä uudelleen myöhemmin" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Kohteen %s avaaminen ei onnistunut" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Väärä PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Tili on jo käytössä" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Kopioi linkki" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Kopioi osoite" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Tallenna alkuperäinen" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Avaa selaimessa" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Tallenna kuva" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Poista kuva napsauttamalla" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Lisää kuva napsauttamalla" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Seuraa" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Lopeta seuraaminen" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s twiittasi uudelleen %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s twiittasi" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d uusi twiitti!" msgstr[1] "%d uutta twiittiä!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Koti" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d uusi viesti käyttäjältä %s" msgstr[1] "%d uutta viestiä käyttäjältä %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Uusi yksityinen viesti käyttäjältä %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Yksityisviestit" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d lukematon)" msgstr[1] "(%d lukematonta)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listat" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Suojattu profiili" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Twiittaa käyttäjälle @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Twiitin näyttäminen epäonnistui" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Uudelleentwiittaukset" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Suosikit" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Lähde" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Twiitin tiedot" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Nyt" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%d min" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%d t" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Etsi" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Avaa tili" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Uusi maininta käyttäjältä @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Maininnat" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Yksityiskeskustelu" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Valitse banneri" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Valitse avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Seuraava" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Kuva ei täytä vähimmäiskokovaatimuksia:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Vähimmäisleveys: %d pikseli" msgstr[1] "Vähimmäisleveys: %d pikseliä" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Vähimmäiskorkeus: %d pikseli" msgstr[1] "Vähimmäiskorkeus: %d pikseliä" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Hei, #Corebird'in uusi versio on nyt saatavilla! \\ (•◡•) / #cool " "#newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Asetukset" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Median enimmäiskoko" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "Mt" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Vieritä automaattisesti uusien twiittien myötä" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Kaksoisnapsautuksen aktivointi" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Käyttöliittymä" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Uusissa twiiteissä" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Toiminnot" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Uusissa maininnoissa" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Uusissa viesteissä" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Ei koskaan" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Joka" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "5 pino" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "10 pino" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "25 pino" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "50 pino" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Ilmoitukset" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Pyöreät avatarit" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Poista lopussa olevat hashtagit" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Poista medialinkit" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Twiitit" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Tekstileikkeitä ei ole määritetty." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "Voit aktivoida tekstileikkeet kirjoittamalla avainsanan ja painamalla TAB." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Tekstileikkeet" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Tietoja" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Lopeta" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Luotu" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Tilannut" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Tietoja - Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Käyttää Dave Gandyn tekemää Font Awesomea - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Lähetä" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Lataa lisää" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Lainaa" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Poista" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Suosikki" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Vastaa" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Näytä tämän tilin asetukset" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Avaa uudessa ikkunassa" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Luo uusi lista" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nimi:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Luo" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Käyttäjät" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Kirjoita twiitti" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Kirjoita yksityisviesti" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Lisää listalle tai poista listalta" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Estetty" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Uudelleentwiittaukset poistettu käytöstä" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Seuraa sinua" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seuraajia" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Seuraa" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Näytä määritetyt tilit" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Twiittaa" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Uusi twiitti" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Uusi tili" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Pyydä PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Vahvista" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Twiittaa uudelleen" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Lisää twiitti suosikkeihin" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Vastaa twiittiin" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Lisää" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Tilaa" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Lopeta tilaus" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Aloita uusi keskustelu" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Osallistujat:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Aloita" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Tilaajat:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Jäsenet:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Tehnyt:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Tehty:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Muokkaa" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Tila:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Yksityinen" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Julkinen" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Lisää uusi suodatin" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Lopeta estäminen" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Tilin asetukset" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nimi" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Verkkosivusto" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Käynnistä automaattisesti" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Haluatko varmasti poistaa tämän tilin?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Takaisin" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Lisää uusi tekstileike" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Avainsana" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Korvike" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird on GTK+:lla toteutettu Twitter-sovellus, joka tarjoaa muun muassa " "yksityisviestit, ilmoitukset twiiteistä ja keskustelunäkymän." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Lisäominaisuuksiin kuuluu muun muassa videoiden katselu suoraan " "sovelluksesta, useat upotetut kuvat, listat, suodattimet, useat tilit jne." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Yleinen aikajana Corebirdissä" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Tyypillinen Twitter-profiili." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Tilin asetuksia, kuten nimeä, verkkosivustoa, kuvausta ja kuvaa on " "mahdollista muuttaa." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter-sovellus" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Käytä Twitteriä työpöytäsovelluksella" corebird-1.1/po/fr.po000066400000000000000000000402461260276623600145510ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Guillaume Hayot, 2015 # newincpp , 2014 # Seboss666 , 2015 # Seboss666 , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: French (http://www.transifex.com/corebird/corebird/language/" "fr/)\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Sélectionner une image" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Annuler" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Choisir" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Ajouter ou supprimer des utilisateurs de la liste" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Sauvegarder" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Vous n'avez aucune liste." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modifier les filtres" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Correspond" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Ne correspond pas" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Aucune entrée trouvée" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Réessayer" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Vous n'avez pas de encore compte ?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Créer un compte " #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Non autorisé. La plus part du temps, cela veut dire qu'il y as un problème " "avec les serveurs Twitter et que vous devriez réessayer plus tard." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Impossible d'ouvrir %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN erroné" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Compte déjà en utilisation" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copier le lien" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copier l'URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Sauvegarder l'original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Ouvrir dans un navigateur" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Sauvegarder l'image" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Cliquez pour supprimer l'image" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Cliquez pour ajouter une image" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Suivre" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Se désabonner" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweetée %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tweeté" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nouveau tweet !" msgstr[1] "%d nouveaux tweets !" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Accueil" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nouveau message de %s" msgstr[1] "%d nouveaux messages de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nouveau Message privé de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Messages privés" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d non lu)" msgstr[1] "(%d non lus)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Lists" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Profile protégée" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet à @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoris " #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Source" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Détails du tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Maintenant" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Researcher" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Connexion au compte" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nouvelles mentions de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Mentions" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversation directe" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "List" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Sélectionner une bannière" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Sélectionner un avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Suivant" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "L'image est trop petite:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Largeur minimale : %d pixel" msgstr[1] "Largeur minimale : %d pixels" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Hauteur minimale : %d pixel" msgstr[1] "Hauteur minimale : %d pixels" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Préférences" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Taille maximum des medias" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "Mo" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "défilement automatique des lors de tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Activation par double clic" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interface" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Au moment de nouveaux tweets" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Actions" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Au moment de nouvelles mentions" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Au moment de nouveaux messages" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Jamais" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "à chaque fois" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Pile 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Pile 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Pile 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Pile 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notifications" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatars ronds" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Supprimer les hashtags superflus" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Supprimer les liens vers les média" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "À propos" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Quitter" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Créée" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "S'inscrire" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "A propos de Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Utilise la Font Awesome par Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Envoyer" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Charger plus" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Citer" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Supprimer" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favori" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Répondre" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Afficher les paramètres de ce compte" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Ouvrir dans une nouvelle fenêtre" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Créer une Nouvelle Liste" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nom :" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Créer" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Utilisateurs" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "écrire un nouveau Tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Écrire un message direct" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Ajouter/Retirer de la Liste" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloqué" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets désactivés" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Vous suit" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Abonnés" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Abonnements" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Afficher les comptes configurés" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Composer un tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nouveau tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nouveau compte" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN :" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Demander le PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirmer" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retweeter le tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Ajouter aux favoris" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Répondre au tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Plus" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "S'abonner" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Se désabonner" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Démarrer une nouvelle conversation" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Avec :" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Go" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Abonnés :" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Membres :" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Créateur :" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Créé à :" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Éditer" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mode :" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privé" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Public" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Ajouter un nouveau filtre" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Débloquer" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Paramètres du compte" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nom" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Site Web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Démarrage auto" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Voulez-vous réellement supprimer ce compte ?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Retour" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird est un client Twitter natif en GTK+ proposant les fonctions vitales " "telles que les messages directs (dm), les notifications, les vues en " "conversations." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Les fonctions additionnelles incluent le visionnage en local des vidéos, les " "insertions multiples d'images, les listes, les filtres, les comptes " "multiples, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Vue générique de la timeline lors de l'utilisation de Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Profil Twitter standard." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Les paramètres de compte comme le nom, le site web, la description et " "l'avatar peuvent être modifiés." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Client Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Utilisez Twitter depuis une application bureau classique" corebird-1.1/po/hu.po000066400000000000000000000340771260276623600145630ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Peter Borsa , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Hungarian (http://www.transifex.com/corebird/corebird/" "language/hu/)\n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Kép kiválasztása" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Mégse" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Mentés" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Szűrő módosítása" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Újra" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Nincs még felhasználói fiókja?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Hibás PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "A felhasználói fiók már használatban" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Link másolása" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "URL másolása" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Megnyitás a böngészőben" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Kép mentése" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Követés" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" msgstr[1] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Home" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d új üzenet %s felhasználótól" msgstr[1] "%d új üzenet %s felhasználótól" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Új személyes üzenet %s felhasználótól" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Személyes üzenetek" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" msgstr[1] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listák" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Védett profil" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Kedvencek" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Forrás" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Tweet részletek" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Most" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Keresés" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Avatar kiválasztása" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Következő" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Minimum szélesség: %d pixel" msgstr[1] "Minimum szélesség: %d pixel" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Minimum magasság: %d pixel" msgstr[1] "Minimum magasság: %d pixel" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Beállítások" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Soha" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Minden" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Értesítések" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweetek" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Névjegy" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Kilépés" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Létrehozva" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Corebird-ről" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Küldés" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Törlés" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Válasz" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Megnyitás új ablakban" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Új lista létrehozása" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Név:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Létrehozás" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Felhasználók" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Blokkolva" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Követők" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Követve" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Tweet írása" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Új tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Új felhasználói fiók" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "PIN kérése" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Megerősítés" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Feliratkozás" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Leiratkozás" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Feliratkozók:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Tagok:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Szerkesztés" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privát" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Publikus" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Név" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Weboldal" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Vissza" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter kliens" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/id_ID.po000066400000000000000000000373751260276623600151230ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Krisan Alfa Timur , 2015 # mhy , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/corebird/" "corebird/language/id_ID/)\n" "Language: id_ID\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Pilih Gambar" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Batal" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Memilih" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Tambah ke atau Hapus Pengguna Dari Daftar" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Simpan" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Anda tidak memiliki daftar." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Ubah Penyaringan" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Cocok" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Tidak cocok" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Entri tidak ditemukan" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Coba lagi" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Belum memiliki akun?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Buat satu" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Tidak sah. Sebagian besar waktu, ini berarti bahwa ada sesuatu yang salah " "dengan server Twitter dan Anda harus mencoba lagi nanti" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Tidak bisa membuka %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Salah PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Akun sudah digunakan" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Salin tautan" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Salin URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Simpan Asli" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Buka di Peladen" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Simpan Gambar" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Klik untuk hapus gambar" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Klik untuk tambah gambar" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Mengikuti" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Batal mengikuti" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweeted %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s tweeted" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d Tweets! baru" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Halaman depan" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d Pesan baru dari %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Pesan baru langsung dari %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Pesan Langsung" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d belum dibaca)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Daftar" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Profil dilindungi" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet untuk @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Kesukaan" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Sumber" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Tweet Detil" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Sekarang" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Pencarian" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Bukan Akun" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Baru Menyebutkan dari @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menyebutkan" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Percakapan Langsung" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Daftar" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Pilih gambar latar" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Pilih avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Berikutnya" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Gambar tidak memenuhi persyaratan ukuran minimum:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Lebar minimum: %d piksel" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Tinggi minimum: %d piksel" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Hai, coba lihat versi yang baru dari #Corebird! \\ (•◡•) / #keren " "#yangbaruselalulebihbaik" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Pengaturan" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Maksimum ukuran media" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Auto scroll pada tweet baru" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Aktivasi klik-ganda" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Antarmuka" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Pada Tweets Baru" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Aksi" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Pada Menyebutkan Baru" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Pada Pesan Baru" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Tidak pernah" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Setiap" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Stack 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Stack 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Stack 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Stack 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notifikasi" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatar bulat" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Hapus hastag sisa" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Hapus tautan media" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Tidak ada potongan-potongan yang terkonfigurasi." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "Kamu bisa mengaktifkan potongan-potongan dengan menuliskan kata kuncinya " "kemudian tekan tombol TAB." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Potongan" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Tentang" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Berhenti" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Dibuat" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Berlangganan ke" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Tentang Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Menggunakan Font Awesome by Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Kirim" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Muat lebih" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Kutipan" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Hapus" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Kesukaan" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Balas" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Tampilkan pengaturan akun ini" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Buka di window baru" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Buat Daftar Baru" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nama:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Membuat" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Pengguna" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Menulis tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Tulis Pesan Langsung" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Tambah ke/Hapus dari daftar" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Diblokir" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets dinonaktifkan" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Mengikuti anda" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Pengikut" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Mengikuti" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Tampilakn pengaturan akun" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Menulis tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Tweet baru" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Akun Baru" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Permintaan PIN:" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Konfirmasi" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retweet tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Tweet kesukaan" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Balas ke tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Lebih banyak" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Langganan" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Berhenti langganan" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Mulai percakapan baru" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Dengan:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Pergi" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Pelanggan:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Anggota:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Pembuat:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Dibuat di:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Ubah" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Mode:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Rahasia" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Umum" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Tambah Penyaringan Baru" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Lepaskan blokir" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Pengaturan Akun" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nama" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Situs" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Mulai Otomatis" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Anda yakin akan menghapus akun ini?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Kembali" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Tambah potongan baru" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Kata Kunci" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Pergantian" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird adalah GTK+ twitter klien native yang menyediakan fitur penting " "seperti Pesan Langsung (DMS), tweet pemberitahuan, pemandangan percakapan." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Fitur tambahan termasuk melihat video lokal, beberapa gambar di baris, " "Daftar, Penyaring, beberapa akun, dll" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Tampilan timeline generik ketika menggunakan Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Khas profil Twitter." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Setelan akun seperti Nama, Website, Deskripsi dan Avatar dapat dikonfigurasi." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter Klien" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Gunakan Twitter dari aplikasi desktop normal" corebird-1.1/po/it.po000066400000000000000000000366131260276623600145610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Daniele Napolitano , 2014 # Nicola Stanislao Vitale , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Italian (http://www.transifex.com/corebird/corebird/language/" "it/)\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Cita il tweet" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Selezione immagine" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Annulla" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Scegli" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Aggiungi o rimuovi un utente dalla lista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Salva" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Non hai nessuna lista" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modifica filtro" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Corrispondenze" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Non corrisponde" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Caricamento in corso..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Nessun risultato trovato" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Riprova" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Non hai ancora un account?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Creane uno" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Non autorizzato. Solitamente questo vuol dire che c'è qualche problema con i " "server di Twitter e dovesti riprovare più tardi." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Non posso aprire %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN sbagliato" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Account già in uso" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copia link" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copia URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Salva originale" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Apri nel browser" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Salva immagine" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Clicca per rimuovere l'immagine" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Clicca per aggiungere un'immagine" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Segui" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Non seguire" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s ha ritwittato %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s ritwittato" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nuovo Twett!" msgstr[1] "%d nuovi Tweet!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Home" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nuovo messaggio da %s" msgstr[1] "%d nuovi messaggi da %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nuovo messaggio diretto da %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Messaggi diretti" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d non letto)" msgstr[1] "(%d non letti)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Liste" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Profilo protetto" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Twitta a @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweet" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Preferiti" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Sorgente" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Dettagli tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Adesso" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Cerca" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Apri account" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nuova menzione da @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menzioni" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversazione diretta" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Seleziona banner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Seleziona avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Prossima" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "L'immagine non ha le dimensioni minime richieste:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Dimensione minima: %d pixel" msgstr[1] "Dimensione minima: %d pixel" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Altezza minima: %d pixel" msgstr[1] "Altezza minima: %d pixel" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Ehi, scarica la nuova versione di #Corebird \\ (•◡•) / #cool " "#newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Impostazioni" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Dimensioni massime file multimediale" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Scorrimento automatico con nuovi tweet" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Doppio-click per attivare" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfaccia" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Azioni" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Mai" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Sempre" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notifiche" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweet" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Informazioni su..." #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Esci" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Creato" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Sottoscritto a" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Informazioni su Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Invia" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Carica altri" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cita" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Elimina" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostra le impostazioni di questo account" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Apri in una nuova finestra" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Crea una nuova lista" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nome:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Crea" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Utenti" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Componi tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Scrivi un messaggio diretto" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Aggiunti/rimuovi dalla lista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloccato" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweet disabilitati" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Ti seguono" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Followers" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Following" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostra gli account configurati" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nuovo tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nuovo account" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Richiedi PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Conferma" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Ritwitta il tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Tweet preferito" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Rispondi al tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Altro" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Sottoscrivi" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Rimuovi sottoscrizione" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Inizia una nuova conversazione" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Con:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Vai" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Iscritti:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Membri:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Creatore:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Creata il:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Modifica" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modalità:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privata" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Pubblica" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Aggiungi nuovo filtro" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Impostazioni account" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nome" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Sito web" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Avvio automatico" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Vuoi davvero rimuovere questo account?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Indietro" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird è un client twitter nativo GTK+ che fornisce funzioni vitali come " "messaggi diretti (DM), notifiche dei tweet e vista delle conversazioni." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Client Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Usa Twitter come una normale applicazione desktop" corebird-1.1/po/ja.po000066400000000000000000000353711260276623600145370ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # kumar8600 , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Japanese (Japan) (http://www.transifex.com/corebird/corebird/" "language/ja_JP/)\n" "Language: ja_JP\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "画像を選択する" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "キャンセル" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "選択" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "保存" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "一致" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "一致しない" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "エントリーがありません" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "許可されていません。大抵の場合Twitterのサーバーがなにかおかしくなったというこ" "とですから、あとでもう一度試してみてください" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "誤ったPIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "リンク アドレスをコピー" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "ブラウザーで開く" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "画像を保存" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "フォロー" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "フォロー解除" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s が %s をリツイート" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s がツイート" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "ホーム" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "%s からダイレクトメッセージ" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "ダイレクトメッセージ" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "リスト" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "非公開プロフィール" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "@%s にツイート" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "リツイート" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "お気に入り" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "ソース" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "ツイートの詳細" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "現在" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "検索" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "アカウントを開く" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "@%s からメンション" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "メンション" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "設定" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "インターフェイス" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "アクション" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "しない" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "全て" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "5 件溜まったら" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "10 件溜まったら" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "25 件溜まったら" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "50 件溜まったら" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "通知" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "ツイート" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "このアプリケーションについて" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "終了" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "既成" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "購読中" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Corebird について" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" "Dave Gandy - http://fontawesome.io の素晴らしいフォントを使っています。" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "送信" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "更に読み込む" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "引用する" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "削除" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "リストの新規作成" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "名前:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "作成" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "ユーザー" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "ツイートの編集" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "ダイレクトメッセージを書く" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "リストへ追加、削除する" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "ブロック済み" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "フォローされている" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "新着ツイート" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "承認" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "リツイートする" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "お気に入りに登録する" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "返信する" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "詳細" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "購読" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "購読解除" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "新たな会話を始める" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "相手:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "始める" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "購読者:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "メンバー:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "作成者:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "作成時刻:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "編集" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "モード:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "非公開" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "公開" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird はGTK+ネイティブなTwitterクライアントで、ダイレクトメッセージ " "(DM) ・ツイート通知・会話ビューといった重要機能を提供します。" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter Client" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/lt.po000066400000000000000000000414161260276623600145610ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Moo, 2014-2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 09:04+0000\n" "Last-Translator: Moo\n" "Language-Team: Lithuanian (http://www.transifex.com/corebird/corebird/" "language/lt/)\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" "%100<10 || n%100>=20) ? 1 : 2);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Cituoti tauškalą" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Pasirinkite paveikslą" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Atšaukti" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Pasirinkti" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Pridėti į arba Pašalinti Naudotoją iš Sąrašo" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Išsaugoti" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Jūs neturite sąrašų." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Keisti Filtrą" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Sutampa" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Nesutampa" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Įkeliama..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Nerasta įrašų" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Pakartoti" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Dar neturite paskyros?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Susikurkite paskyrą" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Neleistina prieiga. Daugelyje atvejų, tai reiškia Twitter serveriuose " "įvykusius nesklandumus, tad vėliau, turėtumėte pabandyti dar kartą" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Nepavyko atidaryti %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Neteisingas PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Paskyra jau yra naudojama" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Kopijuoti nuorodą" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Kopijuoti URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Išsaugoti Originalą" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Atidaryti Naršyklėje" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Išsaugoti paveikslą" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Spustelėkite, kad pašalintumėte paveikslą" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Spustelėkite, kad pridėtumėte paveikslą" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Sekti" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Nustoti sekti" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s persiuntė naudotojo %s tauškalą" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s išsiuntė tauškalą" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d naujas Tauškalas!" msgstr[1] "%d nauji Tauškalai!" msgstr[2] "%d naujų Tauškalų!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Pradžia" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d naujas Pranešimas nuo %s" msgstr[1] "%d nauji Pranešimai nuo %s" msgstr[2] "%d naujų Pranešimų nuo %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Naujas tiesioginis pranešimas nuo %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Tiesioginiai Pranešimai" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d neperskaitytas)" msgstr[1] "(%d neperskaityti)" msgstr[2] "(%d neperskaitytų)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Sąrašai" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Apsaugotas profilis" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Siųsti Tauškalą @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Nepavyko parodyti tauškalo" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Persiųsti tauškalai" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Mėgstami" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Šaltinis" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Išsamiau apie Tauškalą" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Dabar" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dmin." #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dval." #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Paieška" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Atidaryti Paskyrą" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Naujas Paminėjimas nuo @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Paminėjimai" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Tiesioginis Pokalbis" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Sąrašas" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Pasirinkite reklamjuostę" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Pasirinkite avatarą" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Kitas" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Paveikslas neatitinka minimalių dydžio reikalavimų:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Minimalus plotis: %d taškas" msgstr[1] "Minimalus plotis: %d taškai" msgstr[2] "Minimalus plotis: %d taškų" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Minimalus aukštis: %d taškas" msgstr[1] "Minimalus aukštis: %d taškai" msgstr[2] "Minimalus aukštis: %d taškų" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Labas, pažvelk į šią naują #Corebird versiją! \\ (•◡•) / #jega " "#naujayravisadageriau" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Nustatymai" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Maksimalus media dydis" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Automatiškai slinkti, esant naujiems tauškalams" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Aktyvavimas dvigubu spragtelėjimu" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Sąsaja" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Esant Naujiems Tauškalams" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Veiksmai" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Esant Naujiems Paminėjimams" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Esant Naujiems Pranešimams" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Niekada" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Kiekvienam" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Dėklui iš 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Dėklui iš 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Dėklui iš 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Dėklui iš 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Perspėjimai" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Apvalinti avatarus" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Šalinti besivelkančius saitažodžius" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Šalinti media nuorodas" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tauškalai" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Nėra sukonfigūruotų iškarpų." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "Aktyvinkite iškarpas, įrašę raktažodį ir nuspausdami TAB klavišą." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Iškarpos" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Apie" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Baigti" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Sukurta" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Jūsų prenumeratos" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Apie Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Naudojamas Font Awesome pagal Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Siųsti" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Įkelti daugiau" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cituoti" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Ištrinti" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Mėgstamas" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Atsakyti" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Rodyti šios paskyros nustatymus" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Atidaryti naujame lange" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Sukurti Naują Sąrašą" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Pavadinimas:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Sukurti" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Naudotojai" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Rašyti Tauškalą" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Rašyti Tiesioginį Pranešimą" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Pridėti į/Pašalinti iš Sąrašo" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Užblokuotas" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Tauškalų persiuntimas išjungtas" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Seka paskui jus" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Sekėjų" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Seka" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Rodyti konfigūruotas paskyras" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Rašyti tauškalą" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Naujas tauškalas" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nauja Paskyra" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Užklausti PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Patvirtinti" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Persiųsti tauškalą" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Mėgstamas tauškalas" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Atsakyti į tauškalą" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Daugiau" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Prenumeruoti" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Atsisakyti Prenumeratos" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Pradėti naują pokalbį" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Su:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Pirmyn" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Prenumeratoriai:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Nariai:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Kūrėjas:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Sukurta:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Redaguoti" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Veiksena:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privatus" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Viešas" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Pridėti Naują Filtrą" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Atblokuoti" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Paskyros Nustatymai" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Vardas" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Tinklapis" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Paleisti įjungus" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Ar tikrai norite ištrinti šią paskyrą?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Grįžti" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Pridėti Naują Iškarpą" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Raktažodis" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Pakeitimas" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird yra savas GTK+ twitter klientas, kuris suteikia svarbiausias " "ypatybes, tokias kaip Tiesioginiai Pranešimai (TP), tauškalų perspėjimai, " "pokalbių rodiniai." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Papildomas ypatybes sudaro vietinė vaizdo įrašų peržiūra, kelių įterptų " "paveikslėlių galimybė, Sąrašai, Filtrai, kelių paskyrų galimybė ir t. t." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Bendrinis laiko juostos rodinys, naudojant Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Tipinis Twitter profilis." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Paskyros nustatymai, tokie kaip Vardas, Tinklalapis, Aprašas ir Avataras " "gali būti konfigūruojami." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter Klientas" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Naudokitės Twitter normalioje darbalaukio programoje" corebird-1.1/po/nl.po000066400000000000000000000406541260276623600145560ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Geert Wirken , 2014 # Heimen Stoffels , 2014-2015 # Heimen Stoffels , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 10:23+0000\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: Dutch (http://www.transifex.com/corebird/corebird/language/" "nl/)\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Tweet citeren" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Afbeelding selecteren" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Annuleren" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Kiezen" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Gebruiker toevoegen aan of verwijderen uit lijst" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Opslaan" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "U heeft geen lijsten." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Filter aanpassen" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Overeenkomsten" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Komt niet overeen" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Bezig met laden..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Geen invullingen gevonden" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Opnieuw proberen" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Heeft u nog geen account?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Maak er een aan!" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Niet-geautoriseerd. Meestal betekent dit dat er iets mis is met de Twitter-" "servers en dat u het later opnieuw moet proberen" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Het is niet gelukt om %s te openen" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Verkeerde PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Account is al in gebruik" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Link kopiëren" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "URL kopiëren" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Origineel opslaan" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Openen in webbrowser" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Afbeelding opslaan" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Klik om de afbeelding te verwijderen" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Klik om een afbeelding toe te voegen" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Volgen" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Ontvolgen" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweette %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s getweet" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nieuwe tweet!" msgstr[1] "%d nieuwe tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Tijdlijn" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nieuw bericht van %s" msgstr[1] "%d nieuwe berichten van %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nieuw direct bericht van %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Directe Berichten" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d ongelezen)" msgstr[1] "(%d ongelezen)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Lijsten" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Afgeschermd profiel" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Verstuur een tweet naar @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Kan tweet niet weergeven" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "favorieten" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Bron" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Details van tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Nu" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%du" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Zoeken" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Account openen" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nieuwe vermelding door %s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Vermeldingen" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Direct gesprek" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lijst" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Omslagfoto selecteren" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Profielfoto selecteren" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Volgende" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "De afbeelding voldoet niet aan de minimale grootte-vereisten:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Minimale breedte: %d pixel" msgstr[1] "Minimale breedte: %d pixels" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Minimale hoogte: %d pixel" msgstr[1] "Minimale hoogte: %d pixels" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Hey, probeer deze nieuwe #Corebird-versie! \\ (•◡•) / #cool " "#nieuwisaltijdbeter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Voorkeuren" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Maximale mediagrootte" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Automatisch scrollen bij nieuwe tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Tweet openen d.m.v. dubbelklikken" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Uiterlijk" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Bij nieuwe tweets" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Acties" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Bij nieuwe vermeldingen" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Bij nieuwe berichten" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Nooit" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Elke" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "5 opstapelen" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "10 opstapelen" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "25 opstapelen" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "50 opstapelen" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Meldingen" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Ronde profielfoto's" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Trailing hashtags verwijderen" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Medialinks verwijderen" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Er zijn geen fragmenten ingesteld." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "U kunt fragmenten activeren door het sleutelwoord te typen en daarna op de " "TAB-toets te drukken." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Fragmenten" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Over" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Afsluiten" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Gecreëerd" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Geabonneerd op" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Over Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Gebruikmakend van Font Awesome door Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Versturen" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Meer laden" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Tweet citeren" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Verwijderen" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Toevoegen aan favorieten" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Beantwoorden" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Instellingen van dit account weergeven" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Openen in nieuw venster" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Nieuwe lijst creëren" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Naam:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Creëren" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Gebruikers" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Tweet opstellen" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Direct Bericht schrijven" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Toevoegen aan/Verwijderen uit Lijst" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Geblokkeerd" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets zijn uitgeschakeld" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Volgt u" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Volgers" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Volgend" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Ingestelde accounts weergeven" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Tweet opstellen" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nieuwe tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nieuw account" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "PIN-code aanvragen" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Bevestigen" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Tweet retweeten" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Deze tweet toevoegen aan de favorieten" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Tweet beantwoorden" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Meer" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Abonneren" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Opzeggen" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Nieuw gesprek starten" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Met:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Gaan" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Geabonneerden:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Leden:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Auteur:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Gecreëerd op:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Bewerken" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modus:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privé" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Openbaar" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Nieuw filter toevoegen" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Deblokkeren" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Accountinstellingen" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Naam" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Website" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Automatisch opstarten" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Weet u zeker dat u dit account wilt verwijderen?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Vorige" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Nieuw fragment toevoegen" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Sleutelwoord" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Vervanging" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird is een geïntegreerde GTK+ Twitter-applicatie met ondersteuning voor " "de belangrijke functionaliteiten, zoals Directe Berichten (DM), tweet-" "meldingen en gespreksweergaven." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Extra mogelijkheden zijn het lokaal weergeven van video's, meerdere " "ingebedde afbeeldingen, lijsten, filters, meerdere accounts, etc." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Algemene tijdlijnweergave gebruiken" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Doorsnee Twitter-profiel." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Accountinstellingen, zoals uw naam, website, beschrijving en profielfoto, " "kunnen worden ingesteld." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Twitter-applicatie" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Twitter gebruiken vanuit een normaal desktop-programma" corebird-1.1/po/pl.po000066400000000000000000000411151260276623600145510ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Piotr Drąg , 2014-2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 15:48+0000\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish (http://www.transifex.com/corebird/corebird/language/" "pl/)\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Cytowanie tweeta" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Wybierz obraz" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Anuluj" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Wybierz" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Dodawanie lub usuwanie użytkowników z listy" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Zapisz" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Nie ma żadnych list." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modyfikacja filtru" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Pasujące" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Niepasujące" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Wczytywanie…" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Nie odnaleziono żadnych wpisów" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Ponów" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Nie masz jeszcze konta?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Utwórz konto" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Brak upoważnienia. Zwykle oznacza to, że coś jest nie tak z serwerami " "Twittera i powinno się spróbować później" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Nie można otworzyć %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Błędny numer PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Konto jest już używane" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Skopiuj odnośnik" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Skopiuj adres URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Zapisz oryginał" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Otwórz w przeglądarce" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Zapisz obraz" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Kliknięcie usuwa obraz" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Kliknięcie dodaje obraz" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Obserwuj" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Przestań obserwować" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "Użytkownik %s podał dalej tweet użytkownika %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "Użytkownik %s napisał tweet" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d nowy tweet" msgstr[1] "%d nowe tweety" msgstr[2] "%d nowych tweetów" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Główna" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nowa wiadomość od %s" msgstr[1] "%d nowe wiadomości od %s" msgstr[2] "%d nowych wiadomości od %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nowa wiadomość prywatna od %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Wiadomości prywatne" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d nieprzeczytana)" msgstr[1] "(%d nieprzeczytane)" msgstr[2] "(%d nieprzeczytanych)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listy" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Profil chroniony" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet do @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Nie można wyświetlić tweeta" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Podane dalej" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Ulubione" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Źródło" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Szczegóły tweeta" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Teraz" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%d m" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%d g" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Wyszukaj" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Otwórz konto" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nowa wzmianka od @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Wzmianki" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Prywatna rozmowa" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Wybór banera" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Wybór awatara" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Dalej" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Obraz nie spełnia minimalnych wymaganych wymiarów:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Minimalna szerokość: %d piksel" msgstr[1] "Minimalna szerokość: %d piksele" msgstr[2] "Minimalna szerokość: %d pikseli" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Minimalna wysokość: %d piksel" msgstr[1] "Minimalna wysokość: %d piksele" msgstr[2] "Minimalna wysokość: %d pikseli" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "Hej, #Corebird ma nową wersję! \\ (•◡•) / #super #nowejestzawszelepsze" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Ustawienia" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Maksymalny rozmiar multimediów" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Automatyczne przewijanie do nowych tweetów" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Aktywacja podwójnym kliknięciem" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interfejs" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Po otrzymaniu nowych tweetów" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Działania" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Po otrzymaniu nowych wzmianek" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Po otrzymaniu nowych wiadomości" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Nigdy" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Każdy" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Co pięć" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Co dziesięć" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Co dwadzieścia pięć" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Co pięćdziesiąt" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Powiadomienia" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Okrągłe awatary" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Usuwanie końcowych znaczników #" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Usuwanie odnośników do multimediów" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweety" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Nie skonfigurowano żadnych wstawek." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "Można aktywować wstawkę pisząc słowo kluczowe i naciskając klawisz Tab." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Wstawki" #: ../ui/menu.ui.h:2 msgid "About" msgstr "O programie" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Zakończ" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Utworzono" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Subskrybowano do" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "O programie Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" "Używamy Font Awesome autorstwa Dave’a Gandy’ego — http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Wyślij" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Wczytaj więcej" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Cytuj" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Usuń" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Dodaje do ulubionych" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Odpowiada" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Wyświetla ustawienia tego konta" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Otwiera w nowym oknie" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Utwórz nową listę" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nazwa:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Utwórz" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Użytkownicy" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Napisz tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Napisz prywatną wiadomość" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Dodaj/usuń z listy" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Zablokowany" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Wyłączono podawanie dalej" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Obserwuje cię" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Obserwujący" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Obserwowanie" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Wyświetla skonfigurowane konta" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Tworzy tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Nowy tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nowe konto" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Zażądaj kod PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Potwierdź" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Podaj tweet dalej" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Dodaj tweet do ulubionych" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Odpowiedz na tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Więcej" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Subskrybuj" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Usuń subskrypcję" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Rozpocznij nową rozmowę" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Z:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Przejdź" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Subskrybenci:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Członkowie:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Twórca:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Utworzono:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Modyfikuj" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Tryb:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Prywatny" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Publiczny" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Dodanie nowego filtru" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Odblokuj" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Ustawienia konta" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nazwa" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Strona WWW" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Automatyczne uruchamianie" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Na pewno usunąć to konto?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Wstecz" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Dodanie nowej wstawki" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Słowo kluczowe" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Zamiennik" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird jest klientem Twittera natywnym dla biblioteki GTK+ dostarczającym " "takie ważne funkcje, jak prywatne wiadomości, powiadomienia o tweetach oraz " "widok rozmowy." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Dodatkowe funkcje obejmują lokalne wyświetlanie nagrań wideo i wielu obrazów " "osadzonych w tweetach oraz obsługę list, filtrów i wielu kont na raz." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Oś czasu programu Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Typowy profil Twittera." #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Można konfigurować ustawienia konta, takie jak nazwa, witryna, opis i awatar." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Klient Twittera" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Korzystanie z Twittera w zwykłym programie" corebird-1.1/po/pt_BR.po000066400000000000000000000404721260276623600151510ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Evertton de Lima , 2015 # Mauro Pereira Junior , 2015 # Ricardo Borges Jr. , 2015 # Salomão Carneiro de Brito , 2015 # x_root , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-17 22:34+0000\n" "Last-Translator: Ricardo Borges Jr. \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/corebird/" "corebird/language/pt_BR/)\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "Citar tweet" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Selecionar imagem" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Cancelar" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Escolher" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Adicionar ou remover o usuário da lista" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Salvar" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "Você não tem listas." #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Modificar o filtro" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Corresponde" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Não corresponde" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Carregando..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Nenhuma entrada encontrada" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Tentar novamente" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Não tem uma conta ainda?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Criar uma" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Não autorizado. Na maioria das vezes, isso significa que há algo errado com " "os servidores do Twitter e você deve tentar novamente mais tarde" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Não foi possível abrir %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN errado" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Conta já em uso" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Copiar link" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Copiar URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Salvar original" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Abrir no navegador" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Salvar imagem" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Clique para remover a imagem" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Clique para adicionar imagem" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Seguir" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Deixar de seguir" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s retweetou %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s twittou" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d novo tweet!" msgstr[1] "%d novos tweets!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Início" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d nova mensagem de %s" msgstr[1] "%d novas mensagens de %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Nova mensagem direta de %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Mensagens diretas" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d não lido)" msgstr[1] "(%d não lidos)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Listas" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Perfil protegido" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Tweet para @%s" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "Não possível mostrar o tweet" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Retweets" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Favoritos" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Fonte" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "Detalhes do tweet" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Agora" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dm" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dh" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Pesquisa" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Abrir uma conta" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Nova menção de @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Menções" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Conversa direta" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Lista" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Selecione o banner" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Escolha um avatar" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Próximo" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "A imagem não atende aos requisitos mínimos de tamanho:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Largura mínima: %d pixel" msgstr[1] "Largura mínima: %d pixels" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Altura mínima: %d pixel" msgstr[1] "Altura mínima: %d pixels" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Ei, confira essa nova versão do #Corebird! \\ (•◡•) / #legal " "#novoesempremelhor" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Configurações" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Tamanho máximo de mídia" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "MB" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Rolagem automática de novos tweets" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Ativação do clique-duplo" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Interface" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "Em novos tweets" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Ações" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "Em novas menções" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "Em novas mensagens" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Nunca" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "Todo" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "Pilha 5" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "Pilha 10" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "Pilha 25" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "Pilha 50" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Notificações" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Avatares redondos" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Remover hashtags à direita" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Remover links de mídia" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Tweets" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Nenhum snippet configurado." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" "Você pode ativar snippets digitando a palavra-chave e depois pressionando " "TAB." #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Snippets" #: ../ui/menu.ui.h:2 msgid "About" msgstr "Sobre" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Sair" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Criado" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Inscrever-se" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "Sobre o Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Usando Font Awesome por Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Enviar" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Carregar mais" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Citação" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Excluir" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "Favorito" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Responder" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Mostrar configurações dessa conta" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Abrir em uma nova janela" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Criar nova lista" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Nome:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Criar" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Usuários" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Compor tweet" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Escrever mensagem direta" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Adicionar/remover da lista" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Bloqueado" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Retweets desativados" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Você segue" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Seguidores" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Seguindo" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Mostrar contas configuradas" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Compor tweet" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Novo tweet" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Nova conta" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Pedido de PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Confirmar" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Retweetar tweet" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "Tweet favorito" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Responder ao tweet" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Mais" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Inscreva-se" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Cancelar inscrição" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Iniciar nova conversa" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "Com:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "Ir" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Inscritos:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Membros:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Criador:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Criado em:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Editar" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "Modo:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Privado" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Público" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Adicionar novo filtro" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Desbloquear" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Configurações da conta" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Nome" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Website" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Início automático" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Você realmente quer excluir esta conta?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Voltar" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Adicionar Novo Snippet" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Palavra chave" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Substituição" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" "Corebird é um cliente twitter nativo GTK+ que fornece recursos vitais como " "mensagens diretas (DMs), notificações de tweet, exibição de conversas." #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" "Funcionalidades adicionais incluem visualização de vídeos locais, múltiplas " "imagens em linha, Listas, Filtros, múltiplas contas, entre outros." #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "Visualização da Timeline ao usar o Corebird" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "Perfil típico do Twitter" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" "Configurações da conta como Nome, Website, Descrição e Avatar podem ser " "configurados." #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Cliente Twitter" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "Usar o Twitter a partir de uma aplicação desktop normal" corebird-1.1/po/ru.po000066400000000000000000000433401260276623600145660ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Andrew Makarov, 2015 # Ivlev Denis , 2015 # NetFoHack , 2015 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-09-12 08:49+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Russian (http://www.transifex.com/corebird/corebird/language/" "ru/)\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" "%100>=11 && n%100<=14)? 2 : 3);\n" #: ../src/window/ComposeTweetWindow.vala:119 msgid "Quote tweet" msgstr "" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "Выберите изображение" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "Отмена" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "Выбрать" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "Добавить или удалить пользователя из списка" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "Сохранить" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "У тебя нет списков" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "Изменить фильтр" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "Совпадения" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "Не совпадает" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "Загрузка..." #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "Нет записей" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "Повтор" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "Ещё не зарегистрирован?" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "Создать" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" "Не авторизован. Возможно серверы Твиттер поломались, попробуй немного " "позднее." #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "Не могу открыть %s" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "Не верный PIN" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "Аккаунт уже используется" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "Скопировать ссылку" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "Копировать URL" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "Сохранить оригинал" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "Открыть в браузере" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "Сохранить изображение" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "Удалить изображение" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "Добавить изображение" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "Читать" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "Не читать" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s ретвитнут %s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s твитнут" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "%d новый твит!" msgstr[1] "%d новых твита!" msgstr[2] "%d новых твитов!" msgstr[3] "%d новых твитов!" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "Домой" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "%d новое сообщение от %s" msgstr[1] "%d новых сообщения от %s" msgstr[2] "%d новых сообщений от %s" msgstr[3] "%d новых сообщений от %s" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "Новое сообщение от %s" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "Сообщения" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "(%d не прочитано)" msgstr[1] "(%d не прочитано)" msgstr[2] "(%d не прочитано)" msgstr[3] "(%d не прочитано)" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "Списки" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "Защищённый профиль" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "Твитнуть @%s " #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "Ретвиты" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "Избранные" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "Источник" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "Сейчас" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%dм" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%dч" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "Поиск" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "Открытый аккаунт" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "Новое упоминание от @%s" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "Упоминания" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "Личная беседа" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "Список" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "Выбрать банер" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "Выбрать аватар" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "Следующий" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "Изображение не соответствует минимальным требованиям по размеру:" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "Минимальная ширина: %d пиксель" msgstr[1] "Минимальная ширина: %d пикселя" msgstr[2] "Минимальная ширина: %d пикселей" msgstr[3] "Минимальная ширина: %d пикселей" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "Минимальная высота: %d пиксель" msgstr[1] "Минимальная высота: %d пикселя" msgstr[2] "Минимальная высота: %d пикселей" msgstr[3] "Минимальная высота: %d пикселей" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" "Привет, появилась новая версия #Corebird! \\ (•◡•) / #cool #newisalwaysbetter" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "Настройки" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "Максимальный размер медиа" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "МБ" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "Автопрокрутка к новым твитам" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "Активация по двойному клику" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "Интерфейс" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "К новым твитам" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "Действия" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "К новым упоминаниям" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "К новым сообщениям" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "Никогда" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "Уведомления" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "Округлять аватары" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "Удалить завершающие хэштеги" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "Удалить ссылки на медиа" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "Твиты" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "Настроенных сниппетов нет." #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "Сниппеты" #: ../ui/menu.ui.h:2 msgid "About" msgstr "О программе" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "Выход" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "Создан" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "Подписаться" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "О Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "Использовать шрифт Awesome от Dave Gandy - http://fontawesome.io" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "Отправить" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "Ещё..." #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "Цитата" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "Удалить" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "В избранные" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "Ответить" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "Показать настройки аккаунта" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "Открыть в новом окне" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "Создать новый список" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "Имя:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "Создать" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "Пользователи" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "Написать твит" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "Написать личное сообщение" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "Добавить/Удалить из списка" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "Заблокирован" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "Ретвиты отключены" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "Читают тебя" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "Избранные" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "Читаешь" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "Настройки аккаунтов" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "Написать твит" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "Новый твит" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "Новый аккаунт" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "Запросить PIN" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "Подтвердить" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "Ретвитнуть" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "В избранное" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "Ответить" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "Ещё..." #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "Подписаться" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "Отписаться" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "Начать новую беседу" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "С:" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "Подписчики:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "Участники:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "Создатель:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "Создан:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "Редактировать" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "Приватный" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "Открытый" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "Добавить новый фильтр" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "Разблокировать" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "Настройки аккаунта" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "Имя" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "Вебсайт" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "Автозапуск" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "Вы действительно хотите удалить данный аккаунт?" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "Назад" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "Добавить новый сниппет" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "Ключевое слово" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "Замена" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "Клиент Твиттер" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/po/zh_CN.po000066400000000000000000000333171260276623600151440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Dianjin Wang <1132321739qq@gmail.com>, 2014 # Tong Hui , 2014 msgid "" msgstr "" "Project-Id-Version: Corebird\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-30 16:02+0200\n" "PO-Revision-Date: 2015-03-18 10:26+0000\n" "Last-Translator: Ryan Lerch \n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/corebird/" "language/zh_CN/)\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../src/window/ComposeTweetWindow.vala:119 #, fuzzy msgid "Quote tweet" msgstr "收藏推文" #: ../src/window/ComposeTweetWindow.vala:352 msgid "Select Image" msgstr "选择图像" #: ../src/window/ComposeTweetWindow.vala:353 #: ../src/window/UserListDialog.vala:47 #: ../src/widgets/MultiMediaWidget.vala:152 ../ui/compose-window.ui.h:2 #: ../ui/list-list-entry.ui.h:1 ../ui/list-statuses-page.ui.h:8 #: ../ui/filter-list-entry.ui.h:1 ../ui/modify-filter-dialog.ui.h:2 #: ../ui/user-filter-entry.ui.h:1 ../ui/account-dialog.ui.h:2 #: ../ui/image-crop-dialog.ui.h:1 ../ui/modify-snippet-dialog.ui.h:2 msgid "Cancel" msgstr "取消" #: ../src/window/ComposeTweetWindow.vala:354 msgid "Choose" msgstr "选择" #: ../src/window/UserListDialog.vala:40 msgid "Add to or Remove User From List" msgstr "" #: ../src/window/UserListDialog.vala:48 #: ../src/widgets/MultiMediaWidget.vala:153 #: ../src/window/ImageCropDialog.vala:98 ../ui/list-statuses-page.ui.h:6 #: ../ui/modify-filter-dialog.ui.h:3 ../ui/account-dialog.ui.h:3 #: ../ui/modify-snippet-dialog.ui.h:3 msgid "Save" msgstr "保存" #: ../src/window/UserListDialog.vala:68 msgid "You have no lists." msgstr "" #: ../src/window/ModifyFilterDialog.vala:45 msgid "Modify Filter" msgstr "" #: ../src/window/ModifyFilterDialog.vala:76 msgid "Matches" msgstr "" #: ../src/window/ModifyFilterDialog.vala:78 msgid "Doesn't match" msgstr "" #: ../src/widgets/TweetListBox.vala:100 msgid "Loading..." msgstr "" #: ../src/widgets/TweetListBox.vala:103 ../src/widgets/TweetListBox.vala:151 msgid "No entries found" msgstr "未找到条目" #: ../src/widgets/TweetListBox.vala:111 msgid "Retry" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Don't have an account yet?" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:39 msgid "Create one" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:54 msgid "" "Unauthorized. Most of the time, this means that there's something wrong with " "the Twitter servers and you should try again later" msgstr "" #: ../src/widgets/AccountCreateWidget.vala:65 #, c-format msgid "Could not open %s" msgstr "" #. We just assume that it was the wrong code #: ../src/widgets/AccountCreateWidget.vala:89 msgid "Wrong PIN" msgstr "PIN 码错误" #: ../src/widgets/AccountCreateWidget.vala:116 msgid "Account already in use" msgstr "" #: ../src/widgets/PixbufButton.vala:52 msgid "Copy link" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:34 msgid "Copy URL" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:35 msgid "Save Original" msgstr "" #: ../src/widgets/MultiMediaWidget.vala:74 ../src/TweetInfoPage.vala:455 msgid "Open in Browser" msgstr "在浏览器中打开" #: ../src/widgets/MultiMediaWidget.vala:150 msgid "Save image" msgstr "保存图像" #: ../src/widgets/AddImageButton.vala:35 ../src/widgets/AddImageButton.vala:175 msgid "Click to remove image" msgstr "" #: ../src/widgets/AddImageButton.vala:41 msgid "Click to add image" msgstr "" #: ../src/widgets/FollowButton.vala:43 msgid "Follow" msgstr "关注" #: ../src/widgets/FollowButton.vala:44 msgid "Unfollow" msgstr "取消关注" #: ../src/HomeTimeline.vala:110 #, c-format msgid "%s retweeted %s" msgstr "%s转推了%s" #: ../src/HomeTimeline.vala:113 #, c-format msgid "%s tweeted" msgstr "%s 已发推" #: ../src/HomeTimeline.vala:120 #, c-format msgid "%d new Tweet!" msgid_plural "%d new Tweets!" msgstr[0] "" #: ../src/HomeTimeline.vala:171 msgid "Home" msgstr "主页" #: ../src/DMThreadsPage.vala:369 #, c-format msgid "%d new Message from %s" msgid_plural "%d new Messages from %s" msgstr[0] "" #: ../src/DMThreadsPage.vala:375 #, c-format msgid "New direct message from %s" msgstr "" #: ../src/DMThreadsPage.vala:390 ../src/DMThreadsPage.vala:404 msgid "Direct Messages" msgstr "直接消息" #: ../src/list/DMThreadEntry.vala:106 #, c-format msgid "(%d unread)" msgid_plural "(%d unread)" msgstr[0] "" #: ../src/ListsPage.vala:123 ../src/ListsPage.vala:128 #: ../ui/profile-page.ui.h:9 msgid "Lists" msgstr "列表" #: ../src/ProfilePage.vala:280 msgid "Protected profile" msgstr "受保护的个人资料" #: ../src/ProfilePage.vala:517 #, c-format msgid "Tweet to @%s" msgstr "" #: ../src/TweetInfoPage.vala:279 msgid "Could not show tweet" msgstr "" #: ../src/TweetInfoPage.vala:446 msgid "Retweets" msgstr "" #: ../src/TweetInfoPage.vala:447 ../src/FavoritesTimeline.vala:93 #: ../src/FavoritesTimeline.vala:97 msgid "Favorites" msgstr "收藏" #: ../src/TweetInfoPage.vala:455 msgid "Source" msgstr "来源" #: ../src/TweetInfoPage.vala:466 msgid "Tweet Details" msgstr "" #: ../src/util/Utils.vala:156 msgid "Now" msgstr "现在" #: ../src/util/Utils.vala:158 #, c-format msgid "%dm" msgstr "%d分钟" #: ../src/util/Utils.vala:162 #, c-format msgid "%dh" msgstr "%d小时" #: ../src/SearchPage.vala:298 ../src/SearchPage.vala:307 #: ../ui/search-page.ui.h:1 msgid "Search" msgstr "搜索" #: ../src/Corebird.vala:149 msgid "Open Account" msgstr "打开帐号" #: ../src/MentionsTimeline.vala:102 #, c-format msgid "New Mention from @%s" msgstr "" #: ../src/MentionsTimeline.vala:135 ../src/MentionsTimeline.vala:140 msgid "Mentions" msgstr "提及我的" #: ../src/DMPage.vala:314 msgid "Direct Conversation" msgstr "" #: ../src/ListStatusesPage.vala:376 msgid "List" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:159 msgid "Select banner" msgstr "" #: ../src/widgets/AvatarBannerWidget.vala:174 msgid "Select avatar" msgstr "" #: ../src/window/ImageCropDialog.vala:58 ../ui/image-crop-dialog.ui.h:2 msgid "Next" msgstr "" #: ../src/window/ImageCropDialog.vala:103 msgid "Image does not meet minimum size requirements:" msgstr "" #: ../src/window/ImageCropDialog.vala:104 #, c-format msgid "Minimum width: %d pixel" msgid_plural "Minimum width: %d pixels" msgstr[0] "" #: ../src/window/ImageCropDialog.vala:106 #, c-format msgid "Minimum height: %d pixel" msgid_plural "Minimum height: %d pixels" msgstr[0] "" #: ../src/window/SettingsDialog.vala:81 msgid "" "Hey, check out this new #Corebird version! \\ (•◡•) / #cool " "#newisalwaysbetter" msgstr "" #: ../ui/settings-dialog.ui.h:1 ../ui/menu.ui.h:1 msgid "Settings" msgstr "设置" #: ../ui/settings-dialog.ui.h:2 msgid "Maximum media size" msgstr "" #: ../ui/settings-dialog.ui.h:3 msgid "MB" msgstr "" #: ../ui/settings-dialog.ui.h:4 msgid "Auto scroll on new tweets" msgstr "" #: ../ui/settings-dialog.ui.h:5 msgid "Double-click activation" msgstr "" #: ../ui/settings-dialog.ui.h:6 msgid "Interface" msgstr "" #: ../ui/settings-dialog.ui.h:7 msgid "On New Tweets" msgstr "" #: ../ui/settings-dialog.ui.h:8 msgid "Actions" msgstr "动作" #: ../ui/settings-dialog.ui.h:9 msgid "On New Mentions" msgstr "" #: ../ui/settings-dialog.ui.h:10 msgid "On New Messages" msgstr "" #: ../ui/settings-dialog.ui.h:11 msgid "Never" msgstr "从不" #: ../ui/settings-dialog.ui.h:12 msgid "Every" msgstr "间隔" #: ../ui/settings-dialog.ui.h:13 msgid "Stack 5" msgstr "" #: ../ui/settings-dialog.ui.h:14 msgid "Stack 10" msgstr "" #: ../ui/settings-dialog.ui.h:15 msgid "Stack 25" msgstr "" #: ../ui/settings-dialog.ui.h:16 msgid "Stack 50" msgstr "" #: ../ui/settings-dialog.ui.h:17 msgid "Notifications" msgstr "" #: ../ui/settings-dialog.ui.h:18 msgid "Round avatars" msgstr "" #: ../ui/settings-dialog.ui.h:19 msgid "Remove trailing hashtags" msgstr "" #: ../ui/settings-dialog.ui.h:20 msgid "Remove media links" msgstr "" #: ../ui/settings-dialog.ui.h:21 ../ui/search-page.ui.h:2 #: ../ui/profile-page.ui.h:6 msgid "Tweets" msgstr "推文" #: ../ui/settings-dialog.ui.h:22 msgid "No snippets configured." msgstr "" #: ../ui/settings-dialog.ui.h:23 msgid "You can activate snippets by writing the keyword and pressing TAB." msgstr "" #: ../ui/settings-dialog.ui.h:24 msgid "Snippets" msgstr "" #: ../ui/menu.ui.h:2 msgid "About" msgstr "关于" #: ../ui/menu.ui.h:3 msgid "Quit" msgstr "退出" #: ../ui/user-lists-widget.ui.h:1 msgid "Created" msgstr "已创建" #: ../ui/user-lists-widget.ui.h:2 msgid "Subscribed to" msgstr "订阅到" #: ../ui/about-dialog.ui.h:1 msgid "About Corebird" msgstr "关于 Corebird" #: ../ui/about-dialog.ui.h:2 msgid "Using Font Awesome by Dave Gandy - http://fontawesome.io" msgstr "" #: ../ui/dm-page.ui.h:1 ../ui/compose-window.ui.h:3 msgid "Send" msgstr "发送" #: ../ui/load-more-entry.ui.h:1 msgid "Load more" msgstr "加载更多" #: ../ui/tweet-list-entry.ui.h:1 ../ui/tweet-info-page.ui.h:1 msgid "Quote" msgstr "引用" #: ../ui/tweet-list-entry.ui.h:2 ../ui/list-list-entry.ui.h:4 #: ../ui/list-statuses-page.ui.h:7 ../ui/filter-list-entry.ui.h:2 #: ../ui/account-dialog.ui.h:7 ../ui/modify-snippet-dialog.ui.h:6 msgid "Delete" msgstr "删除" #: ../ui/tweet-list-entry.ui.h:3 msgid "Favorite" msgstr "" #: ../ui/tweet-list-entry.ui.h:4 msgid "Reply" msgstr "" #: ../ui/user-list-entry.ui.h:1 msgid "Show settings of this account" msgstr "" #: ../ui/user-list-entry.ui.h:2 msgid "Open in new window" msgstr "" #: ../ui/new-list-entry.ui.h:1 msgid "Create New List" msgstr "创建新列表" #: ../ui/new-list-entry.ui.h:2 msgid "Name:" msgstr "名称:" #: ../ui/new-list-entry.ui.h:3 msgid "Create" msgstr "创建" #: ../ui/search-page.ui.h:3 ../ui/filter-page.ui.h:1 msgid "Users" msgstr "用户" #: ../ui/compose-window.ui.h:1 msgid "Compose Tweet" msgstr "撰写推文" #: ../ui/profile-page.ui.h:1 msgid "Write Direct Message" msgstr "发消息" #: ../ui/profile-page.ui.h:2 msgid "Add to/Remove from List" msgstr "添至/从列表删除" #: ../ui/profile-page.ui.h:3 msgid "Blocked" msgstr "" #: ../ui/profile-page.ui.h:4 msgid "Retweets disabled" msgstr "" #: ../ui/profile-page.ui.h:5 msgid "Follows you" msgstr "关注您" #: ../ui/profile-page.ui.h:7 msgid "Followers" msgstr "" #: ../ui/profile-page.ui.h:8 msgid "Following" msgstr "" #: ../ui/main-window.ui.h:1 msgid "Show configured accounts" msgstr "" #: ../ui/main-window.ui.h:2 msgid "Compose tweet" msgstr "" #: ../ui/main-window.ui.h:3 msgid "New tweet" msgstr "新推文" #: ../ui/account-create-widget.ui.h:1 msgid "New Account" msgstr "" #: ../ui/account-create-widget.ui.h:2 msgid "PIN:" msgstr "PIN 码:" #: ../ui/account-create-widget.ui.h:3 msgid "Request PIN" msgstr "" #: ../ui/account-create-widget.ui.h:4 ../ui/list-statuses-page.ui.h:12 msgid "Confirm" msgstr "确认" #: ../ui/tweet-info-page.ui.h:2 msgid "Retweet tweet" msgstr "转推" #: ../ui/tweet-info-page.ui.h:3 msgid "Favorite tweet" msgstr "收藏推文" #: ../ui/tweet-info-page.ui.h:4 msgid "Reply to tweet" msgstr "回复推文" #: ../ui/tweet-info-page.ui.h:5 msgid "More" msgstr "更多" #: ../ui/list-list-entry.ui.h:2 msgid "Subscribe" msgstr "订阅" #: ../ui/list-list-entry.ui.h:3 msgid "Unsubscribe" msgstr "取消订阅" #: ../ui/start-conversation-entry.ui.h:1 msgid "Start new conversation" msgstr "" #: ../ui/start-conversation-entry.ui.h:2 msgid "With:" msgstr "" #: ../ui/start-conversation-entry.ui.h:3 msgid "Go" msgstr "前往" #: ../ui/list-statuses-page.ui.h:1 msgid "Subscribers:" msgstr "订阅:" #: ../ui/list-statuses-page.ui.h:2 msgid "Members:" msgstr "成员:" #: ../ui/list-statuses-page.ui.h:3 msgid "Creator:" msgstr "创建人:" #: ../ui/list-statuses-page.ui.h:4 msgid "Created at:" msgstr "创建时间:" #: ../ui/list-statuses-page.ui.h:5 msgid "Edit" msgstr "编辑" #: ../ui/list-statuses-page.ui.h:9 msgid "Mode:" msgstr "模式:" #: ../ui/list-statuses-page.ui.h:10 msgid "Private" msgstr "私人" #: ../ui/list-statuses-page.ui.h:11 msgid "Public" msgstr "公开" #: ../ui/modify-filter-dialog.ui.h:1 msgid "Add New Filter" msgstr "" #: ../ui/user-filter-entry.ui.h:2 msgid "Unblock" msgstr "" #: ../ui/account-dialog.ui.h:1 msgid "Account Settings" msgstr "" #: ../ui/account-dialog.ui.h:4 msgid "Name" msgstr "" #: ../ui/account-dialog.ui.h:5 msgid "Website" msgstr "" #: ../ui/account-dialog.ui.h:6 msgid "Autostart" msgstr "" #: ../ui/account-dialog.ui.h:8 msgid "Do you really want to delete this account?" msgstr "" #: ../ui/image-crop-dialog.ui.h:3 msgid "Back" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:1 msgid "Add New Snippet" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:4 msgid "Keyword" msgstr "" #: ../ui/modify-snippet-dialog.ui.h:5 msgid "Replacement" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:1 msgid "" "Corebird is a native GTK+ twitter client that provides vital features such " "as Direct Messages (DMs), tweet notifications, conversation views." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:2 msgid "" "Additional features include local viewing of videos, multiple inline images, " "Lists, Filters, multiple accounts, etc." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:3 msgid "Generic timeline view when using Corebird" msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:4 msgid "Typical Twitter profile." msgstr "" #: ../data/org.baedert.corebird.appdata.xml.in.h:5 msgid "" "Account settings like Name, Website, Description and Avatar can be " "configured." msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:1 msgid "Twitter Client" msgstr "" #: ../data/org.baedert.corebird.desktop.in.in.h:2 msgid "Use Twitter from within a normal desktop application" msgstr "" corebird-1.1/resources.xml000066400000000000000000000076301260276623600157200ustar00rootroot00000000000000 ui/settings-dialog.ui ui/account-create-widget.ui ui/menu.ui ui/compose-window.ui ui/tweet-list-entry.ui ui/tweet-info-page.ui ui/about-dialog.ui ui/dm-threads-page.ui ui/dm-thread-entry.ui ui/profile-page.ui ui/main-window.ui ui/dm-page.ui ui/search-page.ui ui/user-list-entry.ui ui/load-more-entry.ui ui/start-conversation-entry.ui ui/dm-list-entry.ui ui/dm-placeholder-box.ui ui/lists-page.ui ui/list-statuses-page.ui ui/list-list-entry.ui ui/new-list-entry.ui ui/user-lists-widget.ui ui/filter-page.ui ui/filter-list-entry.ui ui/modify-filter-dialog.ui ui/user-filter-entry.ui ui/main-widget.ui ui/account-dialog.ui ui/media-dialog.ui ui/image-crop-dialog.ui ui/modify-snippet-dialog.ui data/scalable/actions/corebird-compose-symbolic.svg data/scalable/actions/corebird-conversation-symbolic.svg data/scalable/actions/corebird-dms-symbolic.svg data/scalable/actions/corebird-filter-symbolic.svg data/scalable/actions/corebird-mentions-symbolic.svg data/scalable/actions/corebird-new-window-symbolic.svg data/scalable/actions/corebird-retweet-symbolic.svg ui/style.css assets/play.png assets/play@2.png assets/verified-small.png assets/verified-small@2.png assets/verified-large.png assets/verified-large@2.png assets/no_avatar.png assets/no_banner.png corebird-1.1/sql/000077500000000000000000000000001260276623600137555ustar00rootroot00000000000000corebird-1.1/sql/Makefile.am000066400000000000000000000000301260276623600160020ustar00rootroot00000000000000SUBDIRS = accounts init corebird-1.1/sql/accounts/000077500000000000000000000000001260276623600155745ustar00rootroot00000000000000corebird-1.1/sql/accounts/Create.1.sql000066400000000000000000000020341260276623600176560ustar00rootroot00000000000000 PRAGMA user_version = 1; -- SQL schema for an account database CREATE TABLE IF NOT EXISTS `common`( token VARCHAR(100), token_secret VARCHAR(100) ); CREATE TABLE IF NOT EXISTS `info`( id NUMERIC(19,0) PRIMARY KEY, screen_name VARCHAR(30), name VARCHAR(30) ); CREATE TABLE IF NOT EXISTS `dm_threads`( user_id NUMERIC(19,0) PRIMARY KEY, name VARCHAR(40), screen_name VARCHAR(30), last_message VARCHAR(250), last_message_id NUMERIC(19,0), avatar_url VARCHAR (250) ); CREATE TABLE IF NOT EXISTS `dms` ( from_id NUMERIC(19,0), to_id NUMERIC(19,0), from_screen_name VARCHAR(30), to_screen_name VARCHAR(40), from_name VARCHAR(30), to_name VARCHAR(30), timestamp INTEGER(11), avatar_url VARCHAR(250), id NUMERIC (19,0) PRIMARY KEY, text TEXT ); CREATE TABLE IF NOT EXISTS `user_cache`( id NUMERIC(19,0) PRIMARY KEY, screen_name VARCHAR(30), user_name VARCHAR (40), score INTEGER (11) ); INSERT INTO `user_cache` (id, screen_name, name, score) VALUES ('2877682863', 'corebirdclient', 'Corebird', 10); corebird-1.1/sql/accounts/Create.2.sql000066400000000000000000000002041260276623600176540ustar00rootroot00000000000000 PRAGMA user_version = 2; CREATE TABLE IF NOT EXISTS `filters`( id INTEGER PRIMARY KEY AUTOINCREMENT, content VARCHAR(100) ); corebird-1.1/sql/accounts/Makefile.am000066400000000000000000000001421260276623600176250ustar00rootroot00000000000000accountsdir = $(datarootdir)/corebird/sql/accounts dist_accounts_DATA = Create.1.sql Create.2.sql corebird-1.1/sql/init/000077500000000000000000000000001260276623600147205ustar00rootroot00000000000000corebird-1.1/sql/init/Create.1.sql000066400000000000000000000023641260276623600170100ustar00rootroot00000000000000 PRAGMA user_version = 1; CREATE TABLE IF NOT EXISTS `common`( token VARCHAR(255), token_secret VARCHAR(255), update_config INTEGER(11), max_media_per_upload INTEGER(2), photo_size_limit INTEGER(10), short_url_length INTEGER(3), short_url_length_https INTEGER(3), characters_reserved_per_media INTEGER(3) ); -- This table caches information about all the accounts -- the user set up. -- This is helpful so we don't have to initialize -- all the databases just because the user wants -- a list of all his accounts CREATE TABLE IF NOT EXISTS `accounts`( id NUMERIC(19,0) PRIMARY KEY, screen_name VARCHAR(30), name VARCHAR(30), notifications_enabled BOOL, avatar_url VARCHAR(255) ); CREATE TABLE IF NOT EXISTS `user`( id NUMERIC(19,0), name VARCHAR(40), screen_name VARCHAR(40), avatar_name VARCHAR(40), avatar_url VARCHAR(50) ); CREATE TABLE IF NOT EXISTS `profiles`( id NUMERIC(19,0), name VARCHAR(40), screen_name VARCHAR(40) PRIMARY KEY, tweets INTEGER(11), followers INTEGER(11), following INTEGER(11), description VARCHAR(160), avatar_name VARCHAR(100), banner_url VARCHAR(255), banner_name VARCHAR(255), banner_on_disk VARCHAR(255), url VARCHAR(150), location VARCHAR(100), is_following BOOL ); corebird-1.1/sql/init/Create.2.sql000066400000000000000000000005361260276623600170100ustar00rootroot00000000000000 PRAGMA user_version = 2; CREATE TABLE IF NOT EXISTS `snippets`( id INTEGER PRIMARY KEY AUTOINCREMENT, key VARCHAR(20), value VARCHAR(200) ); INSERT INTO `snippets` (key, value) VALUES ('dealwithit', '(•_•) ( •_•)>⌐■-■ (⌐■_■)'); INSERT INTO `snippets` (key, value) VALUES ('tableflip', '(╯°□°)╯︵ ┻━┻'); corebird-1.1/sql/init/Makefile.am000066400000000000000000000001411260276623600167500ustar00rootroot00000000000000initdir = $(datarootdir)/corebird/sql/init dist_init_DATA = Create.1.sql \ Create.2.sql corebird-1.1/src/000077500000000000000000000000001260276623600137455ustar00rootroot00000000000000corebird-1.1/src/Account.vala000066400000000000000000000464751260276623600162260ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Account : GLib.Object { public static const string DUMMY = "screen_name"; public int64 id {public get; private set;} public Sql.Database db {public get; private set;} public string screen_name {public get; public set;} public string name {public get; public set;} public string avatar_url {public get; public set;} public string? banner_url {public get; private set;} public string? website {public get; public set;} public string? description {public get; public set;} public Cairo.Surface avatar_small {public get; private set;} public Cairo.Surface avatar {public get; private set;} public Rest.OAuthProxy proxy {public get; private set;} public UserStream user_stream {public get; private set;} public UserCounter user_counter {public get; private set;} private UserEventReceiver event_receiver; public int64[] friends; public int64[] blocked; public int64[] muted; public int64[] disabled_rts; public Gee.ArrayList filters; public signal void info_changed (string screen_name, string name, Cairo.Surface avatar_small, Cairo.Surface avatar); public Account (int64 id, string screen_name, string name) { this.id = id; this.screen_name = screen_name; this.name = name; this.filters = new Gee.ArrayList (); this.event_receiver = new UserEventReceiver (this); } /** * Initializes the database. All account databases are VersionedDatabases * and are stored in accounts/ID.db. * */ public void init_database () { if (db != null) return; this.db = new Sql.Database (Dirs.config (@"accounts/$id.db"), Sql.ACCOUNTS_INIT_FILE); user_counter = new UserCounter (); user_counter.load (db); this.load_filters (); } /** * Initializes the RestProxy object. * * @param load_secrets If set to true, the token and token_secret will be loaded * from the account's database. * @param force If set to true, we will simply force to create a new * RestProxy object. */ public void init_proxy (bool load_secrets = true, bool force = false) { if (proxy != null && !force) return; this.proxy = new Rest.OAuthProxy (Settings.get_consumer_key (), Settings.get_consumer_secret (), "https://api.twitter.com/", false); this.user_stream = new UserStream (this); this.user_stream.register (this.event_receiver); if (load_secrets) { init_database (); int n_rows = db.select ("common").cols ("token", "token_secret") .run ((vals) => { proxy.token = user_stream.token = vals[0]; proxy.token_secret = user_stream.token_secret = vals[1]; return false; //stop }); if (n_rows < 1) { critical ("Could not load token{_secret} for user %s", this.screen_name); } } } public void uninit () { this.proxy = null; this.user_stream.stop (); this.user_counter.save (this.db); this.user_stream = null; } /** * Loads the small and normally sized avatars from disk. * Normal: accounts/ID.png * Small: accounts/ID_small.png */ public void load_avatar () { string small_path = Dirs.config (@"accounts/$(id)_small.png"); string path = Dirs.config (@"accounts/$(id).png"); this.avatar_small = load_surface (small_path); this.avatar = load_surface (path); info_changed (screen_name, name, avatar, avatar_small); } public void set_new_avatar (Cairo.Surface new_avatar) { string path = Dirs.config (@"accounts/$(id).png"); string small_path = Dirs.config (@"accounts/$(id)_small.png"); Cairo.Surface avatar = scale_surface ((Cairo.ImageSurface)new_avatar, 48, 48); Cairo.Surface avatar_small = scale_surface ((Cairo.ImageSurface)new_avatar, 24, 24); write_surface (avatar, path); write_surface (avatar_small, small_path); this.avatar = avatar; this.avatar_small = avatar_small; } /** * Download the appropriate user info from the Twitter server, * updating the local information stored in this class' local variables * and the information stored in the account's database file. * * @param screen_name The screen name to use for the API call or null in * which case the ID will be used. */ public async void query_user_info_by_screen_name (string? screen_name = null) { if (proxy == null) error ("Proxy not initied"); var call = proxy.new_call (); call.set_function ("1.1/users/show.json"); call.set_method ("GET"); if (screen_name != null) { call.add_param ("screen_name", screen_name); this.screen_name = screen_name; } else { call.add_param ("user_id", this.id.to_string ()); } call.add_param ("skip_status", "true"); Json.Node? root_node = null; try { root_node = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return; } bool values_changed = false; var root = root_node.get_object (); this.id = root.get_int_member ("id"); if (this.name != root.get_string_member ("name")) { this.name = root.get_string_member ("name"); values_changed = true; } if (this.screen_name != root.get_string_member ("screen_name")) { string old_screen_name = this.screen_name; this.screen_name = root.get_string_member ("screen_name"); Utils.update_startup_account (old_screen_name, this.screen_name); values_changed = true; } Json.Array desc_urls = root.get_object_member ("entities").get_object_member ("description") .get_array_member ("urls"); var urls = new TextEntity[desc_urls.get_length ()]; desc_urls.foreach_element ((arr, index, node) => { Json.Object obj = node.get_object (); Json.Array indices = obj.get_array_member ("indices"); urls[index] = TextEntity () { from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1), display_text = obj.get_string_member ("expanded_url"), target = null }; }); this.description = TextTransform.transform (root.get_string_member ("description"), urls, TransformFlags.EXPAND_LINKS); if (root.has_member ("profile_banner_url")) this.banner_url = root.get_string_member ("profile_banner_url"); /* Website URL */ if (root.get_object_member ("entities").has_member ("url")) { this.website = root.get_object_member ("entities").get_object_member ("url") .get_array_member ("urls").get_object_element (0).get_string_member ("expanded_url"); } else this.website = ""; string avatar_url = root.get_string_member ("profile_image_url"); values_changed |= yield update_avatar (avatar_url); if (values_changed) { if (this.db != null) this.save_info (); info_changed (this.screen_name, this.name, this.avatar_small, this.avatar); } } public async void init_information () { var collect_obj = new Collect (4); collect_obj.finished.connect (() => { init_information.callback (); }); query_user_info_by_screen_name.begin (null, () => { collect_obj.emit (); }); load_id_array.begin (collect_obj, "1.1/friendships/no_retweets/ids.json", true, (obj, res) => { Json.Array? arr = load_id_array.end (res); if (arr != null) { this.set_disabled_rts (arr); collect_obj.emit (); } }); load_id_array.begin (collect_obj, "1.1/blocks/ids.json", false, (obj, res) => { Json.Array? arr = load_id_array.end (res); if (arr != null) { this.set_blocked (arr); collect_obj.emit (); } }); load_id_array.begin (collect_obj, "1.1/mutes/users/ids.json", false, (obj, res) => { Json.Array? arr = load_id_array.end (res); if (arr != null) { this.set_muted (arr); collect_obj.emit (); } }); yield; } private async Json.Array? load_id_array (Collect collect_obj, string function, bool direct) { var call = this.proxy.new_call (); call.set_function (function); call.set_method ("GET"); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); collect_obj.emit (); return null; } if (direct) return root.get_array (); else return root.get_object ().get_array_member ("ids"); } /** * Updates the account's avatar picture. * This means that the new avatar will be downloaded if necessary and * scaled appropriately. * * @param url The url of the (possibly) new avatar(optional). */ private async bool update_avatar (string url = "") { string dest_path = Dirs.config (@"accounts/$(id)_small.png"); string big_dest = Dirs.config (@"accounts/$(id).png"); if (url.length > 0 && url == this.avatar_url) { if (GLib.FileUtils.test (dest_path, GLib.FileTest.EXISTS) && GLib.FileUtils.test (big_dest, GLib.FileTest.EXISTS)) return false; } debug ("Using %s to update the avatar(old: %s)", url, this.avatar_url); if (url.length > 0) { var msg = new Soup.Message ("GET", url); SOUP_SESSION.queue_message (msg, (_s, _msg) => { var data_stream = new MemoryInputStream.from_data ((owned)msg.response_body.data, null); string type = Utils.get_file_type (url); Gdk.Pixbuf pixbuf; try { pixbuf = new Gdk.Pixbuf.from_stream(data_stream); pixbuf.save(big_dest, type); data_stream.close (); double scale_x = 24.0 / pixbuf.get_width(); double scale_y = 24.0 / pixbuf.get_height(); var scaled_pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.RGB, pixbuf.has_alpha, 8, 24, 24); pixbuf.scale(scaled_pixbuf, 0, 0, 24, 24, 0, 0, scale_x, scale_y, Gdk.InterpType.HYPER); scaled_pixbuf.save(dest_path, type); debug ("saving to %s", dest_path); this.avatar_small = Gdk.cairo_surface_create_from_pixbuf (scaled_pixbuf, 1, null); this.avatar = Gdk.cairo_surface_create_from_pixbuf (pixbuf, 1, null); } catch (GLib.Error e) { critical (e.message); } this.avatar_url = url; Corebird.db.update ("accounts").val ("avatar_url", url).where_eqi ("id", id).run (); update_avatar.callback (); }); yield; return true; } else { critical ("Not implemented yet"); } return false; } /** * Saves the account info both in the account's database and in the * global one. */ public void save_info () { db.replace ("info").vali64 ("id", id) .val ("screen_name", screen_name) .val ("name", name) .run (); Corebird.db.replace ("accounts").vali64 ("id", id) .val ("screen_name", screen_name) .val ("name", name) .val ("avatar_url", avatar_url) .run (); } /** * Load all the filters from the database. */ private void load_filters () { this.db.select ("filters").cols ("content", "id") .order ("id").run ((cols) => { Filter f = new Filter (cols[0]); f.id = int.parse (cols[1]); filters.add (f); return true; }); } public void add_filter (owned Filter f) { this.filters.add (f); } /** * Checks if any of the filters associated to this acount match * the given tweet. * * @param t The tweet to check for * * @return true iff at least one of the filters match, false otherwise. */ public bool filter_matches (Tweet t) { if (t.source_tweet.author.id == this.id) return false; foreach (Filter f in filters) { if (f.matches (t.get_real_text ())) { return true; } } return false; } public void set_friends (Json.Array friends_array) { this.friends = new int64[friends_array.get_length ()]; debug ("Adding %d friends...", friends.length); for (int i = 0; i < friends_array.get_length (); i ++) { this.friends[i] = friends_array.get_int_element (i); } } public bool follows_id (int64 user_id) { foreach (int64 id in this.friends) if (id == user_id) return true; return false; } public void follow_id (int64 user_id) { this.friends.resize (this.friends.length + 1); this.friends[this.friends.length - 1] = user_id; } public void unfollow_id (int64 user_id) { if (this.friends == null || this.friends.length == 0) { warning ("friends == null"); return; } int64[] new_friends = new int64[this.friends.length]; int o = 0; bool found = false; for (int i = 0; i < this.friends.length; i++) { if (this.friends[i] == user_id) { found = true; continue; } new_friends[o] = this.friends[i]; o ++; } if (found) new_friends.resize (new_friends.length - 1); this.friends = new_friends; } public void set_muted (Json.Array muted_array) { this.muted = new int64[muted_array.get_length ()]; debug ("Add %d muted ids", this.muted.length); for (int i = 0; i < this.muted.length; i ++) { this.muted[i] = muted_array.get_int_element (i); } } public void mute_id (int64 id) { this.muted.resize (this.muted.length + 1); this.muted[this.muted.length - 1] = id; } public void unmute_id (int64 id) { if (this.muted == null || this.muted.length == 0) { warning ("muted == null"); return; } int64[] new_muted = new int64[this.muted.length - 1]; int o = 0; for (int i = 0; i < this.muted.length; i++) { if (this.muted[i] == id) { continue; } muted[o] = this.muted[i]; o ++; } this.muted = new_muted; } public void set_blocked (Json.Array blocked_array) { this.blocked = new int64[blocked_array.get_length ()]; debug ("Add %d blocked ids", this.blocked.length); for (int i = 0; i < this.blocked.length; i ++) { this.blocked[i] = blocked_array.get_int_element (i); } } public void block_id (int64 id) { this.blocked.resize (this.blocked.length + 1); this.blocked[this.blocked.length - 1] = id; } public void unblock_id (int64 id) { if (this.blocked == null || this.blocked.length == 0) { warning ("blocked == null"); return; } int64[] new_blocked = new int64[this.blocked.length - 1]; int o = 0; for (int i = 0; i < this.blocked.length; i++) { if (this.blocked[i] == id) { continue; } blocked[o] = this.blocked[i]; o ++; } this.blocked = new_blocked; } public void set_disabled_rts (Json.Array disabled_rts_array) { this.disabled_rts = new int64[disabled_rts_array.get_length ()]; debug ("Add %d disabled_rts ids", this.disabled_rts.length); for (int i = 0; i < this.disabled_rts.length; i ++) { this.disabled_rts[i] = disabled_rts_array.get_int_element (i); } } public void add_disabled_rts_id (int64 user_id) { this.disabled_rts.resize (this.disabled_rts.length + 1); this.disabled_rts[this.disabled_rts.length - 1] = id; } public void remove_disabled_rts_id (int64 user_id) { if (this.disabled_rts == null || this.disabled_rts.length == 0) { warning ("disabled_rts == null"); return; } int64[] new_disabled_rts = new int64[this.disabled_rts.length - 1]; int o = 0; for (int i = 0; i < this.disabled_rts.length; i++) { if (this.disabled_rts[i] == id) { continue; } disabled_rts[o] = this.disabled_rts[i]; o ++; } this.disabled_rts = new_disabled_rts; } public bool blocked_or_muted (int64 user_id) { foreach (int64 id in this.muted) if (id == user_id) return true; foreach (int64 id in this.blocked) if (id == user_id) return true; return false; } /** Static stuff ********************************************************************/ private static GLib.SList accounts = null; /** * Simply returns a list of user-specified accounts. * The list is lazily loaded from the database * * @return A singly-linked list of accounts */ public static unowned GLib.SList list_accounts () { if (accounts == null) lookup_accounts (); return accounts; } /** * Look up the accounts. Each account has a .db in ~/.corebird/accounts/ * The accounts are initialized with only their screen_name and their ID. */ private static void lookup_accounts () { accounts = new GLib.SList (); Corebird.db.select ("accounts").cols ("id", "screen_name", "name", "avatar_url").run ((vals) => { Account acc = new Account (int64.parse(vals[0]), vals[1], vals[2]); acc.avatar_url = vals[3]; acc.load_avatar (); accounts.append (acc); return true; }); } /** * Adds the given account to the end of the current account list. * * @param acc The account to add. */ public static void add_account (Account acc) { accounts.append (acc); } /** * Removes the acccunt with th given screen name from the account list. * * @param screen_name The screen name of the account to remove. */ public static void remove_account (string screen_name) { foreach (Account a in accounts) { if (a.screen_name == screen_name) { accounts.remove (a); return; } } } /** * Returns an unowned reference to the account with the given screen name. * * @param screen_name The screen name of the account to return * @return An unowned reference to the account object with the given screen name or * null of no such instance could be found. */ public static unowned Account? query_account (string screen_name) { foreach (unowned Account a in accounts) { if (screen_name == a.screen_name) return a; } return null; } public static unowned Account? query_account_by_id (int64 id) { foreach (unowned Account a in accounts) { if (id == a.id) return a; } return null; } } corebird-1.1/src/Corebird.vala000066400000000000000000000372661260276623600163610ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Corebird : Gtk.Application { public static Sql.Database db; public static GLib.Menu account_menu; public static SnippetManager snippet_manager; public signal void account_added (Account acc); public signal void account_removed (Account acc); public signal void account_window_changed (int64? old_id, int64 new_id); const GLib.ActionEntry[] app_entries = { {"show-settings", show_settings_activated }, {"quit", quit_application }, {"show-about-dialog", about_activated }, {"show-dm-thread", show_dm_thread, "(xx)" }, {"mark-seen", mark_seen, "(sx)" }, {"show-window", show_window, "x" }, {"post-json", post_json, "(ss)" } }; public Corebird () throws GLib.Error { GLib.Object(application_id: "org.baedert.corebird", flags: ApplicationFlags.HANDLES_COMMAND_LINE); //register_session: true); snippet_manager = new SnippetManager (); } public override int command_line (ApplicationCommandLine cmd) { this.hold (); string? compose_screen_name = null; OptionEntry[] options = new OptionEntry[2]; options[0] = {"tweet", 't', 0, OptionArg.STRING, ref compose_screen_name, "Shows only the 'compose tweet' window for the given account, nothing else.", "SCREEN_NAME"}; options[1] = {null}; string[] args = cmd.get_arguments (); string*[] _args = new string[args.length]; for (int i = 0; i < args.length; i++) { _args[i] = args[i]; } try { var opt_context = new OptionContext (""); opt_context.set_help_enabled (true); opt_context.add_main_entries (options, GETTEXT_PACKAGE); #if VIDEO opt_context.add_group (Gst.init_get_option_group ()); #endif unowned string[] tmp = _args; opt_context.parse (ref tmp); } catch (GLib.OptionError e) { cmd.print ("Use --help to see available options\n"); quit (); return -1; } open_startup_windows (compose_screen_name); this.release (); return 0; } public override void activate () { open_startup_windows (null); } private void show_settings_activated () { /* We don't set the settings dialog transient to any window because we already save its size */ var dialog = new SettingsDialog (this); dialog.show (); } private void about_activated () { var active_window = get_active_window (); var ad = new AboutDialog (); ad.modal = true; ad.set_transient_for (active_window); ad.show_all (); } public override void startup () { // {{{ base.startup (); new LazyMenuButton (); #if DEBUG GLib.Environment.set_variable ("G_MESSAGES_DEBUG", "all", true); #endif Dirs.create_dirs (); debug ("startup"); Corebird.db = new Sql.Database (Dirs.config ("Corebird.db"), Sql.COREBIRD_INIT_FILE); // Setup gettext GLib.Intl.setlocale(GLib.LocaleCategory.ALL, LOCALEDIR); GLib.Intl.bindtextdomain (GETTEXT_PACKAGE, null); GLib.Intl.bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); GLib.Intl.textdomain(GETTEXT_PACKAGE); // Construct app menu Gtk.Builder builder = new Gtk.Builder (); try { builder.add_from_resource ("/org/baedert/corebird/ui/menu.ui"); } catch (GLib.Error e) { critical (e.message); } GLib.MenuModel app_menu = (MenuModel)builder.get_object ("app-menu"); var acc_menu = app_menu.get_item_link (0, "section"); account_menu = new GLib.Menu (); Utils.load_custom_css (); Utils.load_custom_icons (); Utils.init_soup_session (); Twitter.get ().init (); unowned GLib.SList accounts = Account.list_accounts (); foreach (var acc in accounts) { acc.info_changed.connect (account_info_changed); var show_win_action = new SimpleAction ("show-" + acc.id.to_string (), null); show_win_action.activate.connect (()=> { add_window_for_account (acc); }); add_action(show_win_action); var mi = create_accout_menu_item (acc); account_menu.append_item (mi); } ((GLib.Menu)acc_menu).append_submenu (_("Open Account"), account_menu); this.set_app_menu (app_menu); this.set_accels_for_action ("win.compose-tweet", {Settings.get_accel ("compose-tweet")}); this.set_accels_for_action ("win.toggle-sidebar", {Settings.get_accel ("toggle-sidebar")}); this.set_accels_for_action ("win.switch-page(0)", {"1"}); this.set_accels_for_action ("win.switch-page(1)", {"2"}); this.set_accels_for_action ("win.switch-page(2)", {"3"}); this.set_accels_for_action ("win.switch-page(3)", {"4"}); this.set_accels_for_action ("win.switch-page(4)", {"5"}); this.set_accels_for_action ("win.switch-page(5)", {"6"}); this.set_accels_for_action ("win.switch-page(6)", {"7"}); this.set_accels_for_action ("app.show-settings", {Settings.get_accel ("show-settings")}); this.set_accels_for_action ("app.quit", {"Q"}); this.set_accels_for_action ("win.show-account-dialog", {Settings.get_accel ("show-account-dialog")}); this.set_accels_for_action ("win.show-account-list", {Settings.get_accel ("show-account-list")}); this.add_action_entries (app_entries, this); // If the user wants the dark theme, apply it var gtk_s = Gtk.Settings.get_default (); if (Settings.use_dark_theme ()) { gtk_s.gtk_application_prefer_dark_theme = true; } if (gtk_s.gtk_decoration_layout.contains ("menu")) { gtk_s.gtk_decoration_layout = gtk_s.gtk_decoration_layout.replace ("menu", ""); } } // }}} public override void shutdown () { base.shutdown(); } private GLib.MenuItem create_accout_menu_item (Account account) { var mi = new GLib.MenuItem ("@" + account.screen_name.replace ("_", "__"), "app.show-" + account.id.to_string ()); mi.set_attribute_value ("user-id", new GLib.Variant.int64 (account.id)); return mi; } private void account_info_changed (Account source, string screen_name, string s, Cairo.Surface a, Cairo.Surface b) { for (int i = 0; i < account_menu.get_n_items (); i++){ int64 item_id = account_menu.get_item_attribute_value (i, "user-id", GLib.VariantType.INT64).get_int64 (); if (item_id == source.id) { var new_menu_item = create_accout_menu_item (source); account_menu.remove (i); account_menu.insert_item (i, new_menu_item); return; } } } /** * Open startup windows. * Semantics: Open a window for every account in the startup-accounts array. * If that array is empty, look at all the account and if there is one, open that one. * If there is none, open a MainWindow with a null account. */ private void open_startup_windows (string? compose_screen_name = null) { // {{{ if (compose_screen_name != null) { Account? acc = Account.query_account (compose_screen_name); if (acc == null) { critical ("No account named `%s` is configured. Exiting.", compose_screen_name); return; } // TODO: Handle the 'avatar not yet cached' case acc.init_proxy (); acc.query_user_info_by_screen_name.begin (); var cw = new ComposeTweetWindow (null, acc, null, ComposeTweetWindow.Mode.NORMAL); cw.show(); this.add_window (cw); return; } string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); /* Handle the stupid case where only one item is in the array but it's empty */ if (startup_accounts.length == 1 && startup_accounts[0] == "") startup_accounts.resize (0); uint n_accounts = Account.list_accounts ().length (); if (startup_accounts.length == 0) { if (n_accounts == 1) { add_window_for_screen_name (Account.list_accounts ().nth_data (0).screen_name); } else if (n_accounts == 0) { var window = new MainWindow (this, null); add_window (window); window.show_all (); } else { /* We have multiple configured accounts but still none in autostart. This should never happen but we handle the case anyway by just opening the first one. */ add_window_for_screen_name (Account.list_accounts ().nth_data (0).screen_name); } } else { bool opened_window = false; foreach (string account in startup_accounts) { if (!is_window_open_for_screen_name (account, null)) { if (add_window_for_screen_name (account)) { opened_window = true; } } } /* If we did not open any window at all since all windows for every account in the startups-account array were already open, just open a new window with a null account */ if (!opened_window) { if (n_accounts > 0) { /* Check if *any* of the configured accounts (not just startup-accounts) is not opened in a window */ foreach (Account account in Account.list_accounts ()) if (!is_window_open_for_user_id (account.id, null)) { add_window_for_account (account); return; } } foreach (Gtk.Window w in this.get_windows ()) if (((MainWindow)w).account.screen_name == Account.DUMMY) { return; } var m = new MainWindow (this, null); add_window (m); m.show_all (); } } } // }}} /** * Adds a new MainWindow instance with the account that * has the given screen name. * Note that this only works if the account is already properly * set up and won't warn or fail if if isn't. * * @param screen_name The screen name of the account do add a * MainWindow for. * * @return true if a window has been opened, false otherwise */ public bool add_window_for_screen_name (string screen_name) { unowned GLib.SList accs = Account.list_accounts (); foreach (Account a in accs) { if (a.screen_name == screen_name) { add_window_for_account (a); return true; } } warning ("Could not add window for account '%s'", screen_name); return false; } public void add_window_for_account (Account account) { var window = new MainWindow (this, account); this.add_window (window); window.show_all (); } /** * Checks if there's currently a MainWindow instance open that has a * reference to the account with the given screen name. * (This makes a linear search over all open windows, with a text comparison * in each iteration) * * @param screen_name The screen name to search for * @return TRUE if a window with the account associated to the given * screen name is open, FALSE otherwise. */ public bool is_window_open_for_screen_name (string screen_name, out MainWindow? window = null) { unowned GLib.List windows = this.get_windows (); foreach (Gtk.Window win in windows) { if (win is MainWindow) { if (((MainWindow)win).account.screen_name == screen_name) { window = (MainWindow)win; return true; } } } window = null; return false; } public bool is_window_open_for_user_id (int64 user_id, out MainWindow? window = null) { unowned GLib.List windows = this.get_windows (); foreach (Gtk.Window win in windows) { if (win is MainWindow) { if (((MainWindow)win).account.id == user_id) { window = (MainWindow)win; return true; } } } window = null; return false; } /** * Quits the application, saving all open windows and their geometries. */ private void quit_application () { unowned GLib.List windows = this.get_windows (); string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); if (startup_accounts.length == 1 && startup_accounts[0] == "") startup_accounts.resize (0); if (startup_accounts.length != 0) { base.quit (); return; } string[] account_names = new string[windows.length ()]; int index = 0; foreach (var win in windows) { if (!(win is MainWindow)) continue; var mw = (MainWindow)win; string screen_name = mw.account.screen_name; mw.save_geometry (); account_names[index] = screen_name; index ++; } account_names.resize (index + 1); Settings.get ().set_strv ("startup-accounts", account_names); base.quit (); } /********************************************************/ private void show_dm_thread (GLib.SimpleAction a, GLib.Variant? value) { // Values: Account id, sender_id int64 account_id = value.get_child_value (0).get_int64 (); int64 sender_id = value.get_child_value (1).get_int64 (); MainWindow main_window; if (is_window_open_for_user_id (account_id, out main_window)) { var bundle = new Bundle (); bundle.put_int64 ("sender_id", sender_id); main_window.main_widget.switch_page (Page.DM, bundle); main_window.present (); } else warning ("Window for Account %s is not open, abort.", account_id.to_string ()); } private void mark_seen (GLib.SimpleAction a, GLib.Variant? value) { string screen_name = value.get_child_value (0).get_string (); int64 tweet_id = value.get_child_value (1).get_int64 (); MainWindow main_window; if (is_window_open_for_screen_name (screen_name, out main_window)) { message ("Mark as read..."); } else warning ("No window for Account %s found", screen_name); } private void show_window (GLib.SimpleAction a, GLib.Variant? value) { int64 user_id = value.get_int64 (); MainWindow main_window; if (is_window_open_for_user_id (user_id, out main_window)) main_window.present (); else warning ("TODO: Implement"); } private void post_json (GLib.SimpleAction a, GLib.Variant? value) { string screen_name = value.get_child_value (0).get_string (); string json = value.get_child_value (1).get_string (); json += "\r\n"; MainWindow? win = null; if (is_window_open_for_screen_name (screen_name, out win)) { if (win.account == null) { error ("account is null"); } var fake_call = win.account.proxy.new_call (); win.account.user_stream.parse_data_cb (fake_call, json, json.length, null); } else error ("Window for %s is not open, so account isn't active.", screen_name); } } corebird-1.1/src/DMPage.vala000066400000000000000000000260541260276623600157160ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/dm-page.ui")] class DMPage : IPage, IMessageReceiver, Gtk.Box { public int unread_count { get { return 0; } } public unowned MainWindow main_window { get; set; } public unowned Account account { get; set; } public unowned DeltaUpdater delta_updater { get; set; } public int id { get; set; } [GtkChild] private Gtk.Button send_button; [GtkChild] private CompletionTextView text_view; [GtkChild] private Gtk.ListBox messages_list; [GtkChild] private ScrollWidget scroll_widget; private DMPlaceholderBox placeholder_box = new DMPlaceholderBox (); public int64 user_id; private int64 lowest_id = int64.MAX; private bool was_scrolled_down = false; public DMPage (int id, Account account) { this.id = id; this.account = account; text_view.buffer.changed.connect (recalc_length); messages_list.set_sort_func (ITwitterItem.sort_func_inv); placeholder_box.show (); messages_list.set_placeholder(placeholder_box); scroll_widget.scrolled_to_start.connect (load_older); text_view.size_allocate.connect (() => { if (was_scrolled_down) scroll_widget.scroll_down_next (false, false); }); scroll_widget.vadjustment.value_changed.connect (() => { if (scroll_widget.scrolled_down) { this.was_scrolled_down = true; } else { this.was_scrolled_down = false; } }); } public void stream_message_received (StreamMessageType type, Json.Node root) { // {{{ if (type == StreamMessageType.DIRECT_MESSAGE) { // Arriving new dms get already cached in the DMThreadsPage var obj = root.get_object ().get_object_member ("direct_message"); /* XXX Replace this with local entity parsing */ if (obj.get_int_member ("sender_id") == account.id && obj.has_member ("entities")) { var entries = messages_list.get_children (); int64 dm_id = obj.get_int_member ("id"); foreach (var entry in entries) { var e = (DMListEntry) entry; if (e.user_id == account.id && e.id == -1) { var text = obj.get_string_member ("text"); var urls = obj.get_object_member ("entities").get_array_member ("urls"); var url_list = new TextEntity[urls.get_length ()]; urls.foreach_element((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member("expanded_url"); Json.Array indices = url.get_array_member ("indices"); expanded_url = expanded_url.replace("&", "&"); url_list[index] = TextEntity() { from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1) , target = expanded_url, display_text = url.get_string_member ("display_url") }; }); e.text = TextTransform.transform (text, url_list, 0); e.id = dm_id; break; } } } /* Only handle DMs from the user we are currently chatting with */ if (obj.get_int_member ("sender_id") != this.user_id) return; var text = obj.get_string_member ("text"); if (obj.has_member ("entities")) { var urls = obj.get_object_member ("entities").get_array_member ("urls"); var url_list = new TextEntity[urls.get_length ()]; urls.foreach_element((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member("expanded_url"); Json.Array indices = url.get_array_member ("indices"); expanded_url = expanded_url.replace("&", "&"); url_list[index] = TextEntity() { from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1) , target = expanded_url, display_text = url.get_string_member ("display_url") }; }); text = TextTransform.transform (text, url_list, 0); } var sender = obj.get_object_member ("sender"); var new_msg = new DMListEntry (); new_msg.text = obj.get_string_member ("text"); new_msg.name = sender.get_string_member ("name"); new_msg.screen_name = sender.get_string_member ("screen_name"); new_msg.avatar_url = sender.get_string_member ("profile_image_url"); new_msg.timestamp = Utils.parse_date (obj.get_string_member ("created_at")).to_unix (); new_msg.main_window = main_window; new_msg.user_id = sender.get_int_member ("id"); new_msg.load_avatar (); new_msg.update_time_delta (); delta_updater.add (new_msg); messages_list.add (new_msg); if (scroll_widget.scrolled_down) scroll_widget.scroll_down_next (); } } /// }}} private void load_older () { // {{{ var now = new GLib.DateTime.now_local (); scroll_widget.balance_next_upper_change (TOP); // Load messages // TODO: Fix code duplication account.db.select ("dms").cols ("from_id", "to_id", "text", "from_name", "from_screen_name", "avatar_url", "timestamp", "id") .where (@"(`from_id`='$user_id' OR `to_id`='$user_id') AND `id` < '$lowest_id'") .order ("timestamp DESC") .limit (35) .run ((vals) => { int64 id = int64.parse (vals[7]); if (id < lowest_id) lowest_id = id; var entry = new DMListEntry (); entry.id = id; entry.user_id = int64.parse (vals[0]); entry.timestamp = int64.parse (vals[6]); entry.text = vals[2]; entry.name = vals[3]; entry.screen_name = vals[4]; entry.avatar_url = vals[5]; entry.main_window = main_window; entry.load_avatar (); entry.update_time_delta (now); delta_updater.add (entry); messages_list.add (entry); return true; }); } // }}} public void on_join (int page_id, Bundle? args) { // {{{ int64 user_id = args.get_int64 ("sender_id"); if (user_id == 0) return; this.lowest_id = int64.MAX; this.user_id = user_id; string screen_name; string name = null; if ((screen_name = args.get_string ("screen_name")) != null) { name = args.get_string ("name"); placeholder_box.screen_name = screen_name; placeholder_box.name = name; placeholder_box.avatar_url = args.get_string ("avatar_url"); placeholder_box.load_avatar (); } text_view.set_account (this.account); // Clear list messages_list.foreach ((w) => {messages_list.remove (w);}); // Update unread count DMThreadsPage threads_page = ((DMThreadsPage)main_window.get_page (Page.DM_THREADS)); threads_page.adjust_unread_count_for_user_id (user_id); var now = new GLib.DateTime.now_local (); // Load messages account.db.select ("dms").cols ("from_id", "to_id", "text", "from_name", "from_screen_name", "avatar_url", "timestamp", "id") .where (@"`from_id`='$user_id' OR `to_id`='$user_id'") .order ("timestamp DESC") .limit (35) .run ((vals) => { int64 id = int64.parse (vals[7]); if (id < lowest_id) lowest_id = id; var entry = new DMListEntry (); entry.id = id; entry.user_id = int64.parse (vals[0]); entry.timestamp = int64.parse (vals[6]); entry.text = vals[2]; entry.name = vals[3]; name = vals[3]; entry.screen_name = vals[4]; screen_name = vals[4]; entry.avatar_url = vals[5]; entry.main_window = main_window; entry.load_avatar (); entry.update_time_delta (now); delta_updater.add (entry); messages_list.add (entry); return true; }); account.user_counter.user_seen (user_id, screen_name, name); scroll_widget.scroll_down_next (false, true); // Focus the text entry text_view.grab_focus (); } // }}} public void on_leave () {} [GtkCallback] private void send_button_clicked_cb () { // {{{ if (text_view.buffer.text.length == 0) return; // Withdraw the notification if there is one DMThreadsPage threads_page = ((DMThreadsPage)main_window.get_page (Page.DM_THREADS)); string notification_id = threads_page.get_notification_id_for_user_id (this.user_id); if (notification_id != null) GLib.Application.get_default ().withdraw_notification (notification_id); // Just add the entry now DMListEntry entry = new DMListEntry (); entry.id = -1; entry.user_id = account.id; entry.screen_name = account.screen_name; entry.timestamp = new GLib.DateTime.now_local ().to_unix (); entry.text = GLib.Markup.escape_text (text_view.buffer.text); entry.name = account.name; entry.avatar = account.avatar; entry.update_time_delta (); delta_updater.add (entry); messages_list.add (entry); var call = account.proxy.new_call (); call.set_function ("1.1/direct_messages/new.json"); call.set_method ("POST"); call.add_param ("user_id", user_id.to_string ()); call.add_param ("text", text_view.buffer.text); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } }); // clear the text entry text_view.buffer.text = ""; // Scroll down if (scroll_widget.scrolled_down) scroll_widget.scroll_down_next (); } // }}} [GtkCallback] private bool text_view_key_press_cb (Gdk.EventKey evt) { if (evt.keyval == Gdk.Key.Return && (evt.state & Gdk.ModifierType.CONTROL_MASK) == Gdk.ModifierType.CONTROL_MASK) { send_button_clicked_cb (); return true; } return false; } private void recalc_length () { uint text_length = text_view.buffer.text.length; send_button.sensitive = text_length > 0; } public string? get_title () { return _("Direct Conversation"); } public void create_tool_button (Gtk.RadioButton? group) {} public Gtk.RadioButton? get_tool_button() {return null;} } corebird-1.1/src/DMThreadsPage.vala000066400000000000000000000365541260276623600172370ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/dm-threads-page.ui")] class DMThreadsPage : IPage, IMessageReceiver, ScrollWidget { private bool initialized = false; private int _unread_count = 0; public int unread_count { get { return _unread_count; } set { debug ("Changing unread_count from %d to %d", this._unread_count, value); this._unread_count = value; tool_button.show_badge = (this._unread_count > 0); } } public unowned MainWindow main_window { get; set; } public unowned Account account { get; set; } public unowned DeltaUpdater delta_updater { get; set; } public int id { get; set; } private BadgeRadioToolButton tool_button; private Gee.HashMap thread_map = new Gee.HashMap (Utils.int64_hash_func, Utils.int64_equal_func, DMThreadEntry.equal_func); private StartConversationEntry start_conversation_entry; private int64 max_received_id = -1; private int64 max_sent_id = -1; [GtkChild] private Gtk.ListBox thread_list; private Gtk.Spinner progress_spinner; private Collect dm_download_collect; public DMThreadsPage (int id, Account account) { this.id = id; this.account = account; this.dm_download_collect = new Collect (2); thread_list.set_header_func (default_header_func); thread_list.set_sort_func (dm_thread_entry_sort_func); thread_list.row_activated.connect ((row) => { if (row is StartConversationEntry) ((StartConversationEntry)row).reveal (); else if (row is DMThreadEntry) { var entry = (DMThreadEntry) row; /* We can withdraw the notification here since activating the notification will dismiss it */ if (entry.notification_id != null) { GLib.Application.get_default ().withdraw_notification (entry.notification_id); entry.notification_id = null; } var bundle = new Bundle (); bundle.put_int64 ("sender_id", entry.user_id); main_window.main_widget.switch_page (Page.DM, bundle); } }); start_conversation_entry = new StartConversationEntry (account); start_conversation_entry.start.connect((user_id, screen_name, name, avatar_url) => { var thread_entry = thread_map.get (user_id); if (thread_entry != null) { this.unread_count -= thread_entry.unread_count; } var bundle = new Bundle (); bundle.put_int64 ("sender_id", user_id); bundle.put_string ("screen_name", screen_name); bundle.put_string ("name", name); bundle.put_string ("avatar_url", avatar_url); main_window.main_widget.switch_page (Page.DM, bundle); }); thread_list.add (start_conversation_entry); } public void stream_message_received (StreamMessageType type, Json.Node root) { if (type == StreamMessageType.DIRECT_MESSAGE) { var obj = root.get_object ().get_object_member ("direct_message"); add_new_thread (obj); int64 sender_id = obj.get_int_member ("sender_id"); if (sender_id != account.id) { if (!user_id_visible (sender_id)) { this.unread_count ++; debug ("Increasing global unread count by 1"); } } } } public void on_join (int page_id, Bundle? args) { if (!GLib.NetworkMonitor.get_default ().get_network_available ()) return; if (!initialized) { load_cached (); load_newest (); initialized = true; } } public void on_leave () { start_conversation_entry.unreveal (); } public void load_cached () { // {{{ //Load max message id max_received_id = account.db.select ("dms").cols ("id") .where_eqi ("to_id", account.id).order ("id DESC").limit (1).once_i64 (); max_sent_id = account.db.select ("dms").cols ("id") .where_eqi ("from_id", account.id).order ("id DESC").limit (1).once_i64 (); int n_rows = account.db.select ("dm_threads") .cols ("user_id", "screen_name", "last_message", "last_message_id", "avatar_url", "name") .order ("last_message_id") .run ((vals) => { int64 user_id = int64.parse (vals[0]); var entry = new DMThreadEntry (user_id); entry.screen_name = vals[1]; entry.name = vals[5]; entry.last_message = vals[2]; entry.last_message_id = int64.parse(vals[3]); entry.unread_count = 0; entry.avatar = Twitter.get ().get_avatar (vals[4], (a) => { entry.avatar = a; }); thread_list.add (entry); thread_map.set (user_id, entry); return true; }); if (n_rows == 0 && GLib.NetworkMonitor.get_default ().get_network_available ()) { var row = new Gtk.ListBoxRow (); progress_spinner = new Gtk.Spinner (); progress_spinner.set_size_request (16, 16); progress_spinner.margin = 12; progress_spinner.start (); row.add (progress_spinner); row.activatable = false; thread_list.add (row); } } // }}} public void load_newest () { // {{{ dm_download_collect.finished.connect (() => { remove_spinner (); save_last_messages (); }); var call = account.proxy.new_call (); call.set_function ("1.1/direct_messages.json"); call.set_method ("GET"); call.add_param ("skip_status", "true"); call.add_param ("since_id", max_received_id.to_string ()); call.add_param ("count", "200"); TweetUtils.load_threaded.begin (call, (obj, res) => { try { Json.Node? root = TweetUtils.load_threaded.end (res); on_dm_result (root); } catch (GLib.Error e) { warning (e.message); on_dm_result (null); } }); var sent_call = account.proxy.new_call (); sent_call.set_function ("1.1/direct_messages/sent.json"); sent_call.add_param ("skip_status", "true"); sent_call.add_param ("since_id", max_sent_id.to_string ()); sent_call.add_param ("count", "200"); sent_call.set_method ("GET"); TweetUtils.load_threaded.begin (sent_call, (obj, res) => { try { Json.Node? root = TweetUtils.load_threaded.end (res); on_dm_result (root); } catch (GLib.Error e) { warning (e.message); on_dm_result (null); } }); } // }}} private void on_dm_result (Json.Node? root) { dm_download_collect.emit (); if (root == null) return; var root_arr = root.get_array (); debug ("sent: %u", root_arr.get_length ()); if (root_arr.get_length () > 0) { account.db.begin_transaction (); root_arr.foreach_element ((arr, pos, node) => { var dm_obj = node.get_object (); if (dm_obj.get_int_member ("sender_id") == account.id) save_message (dm_obj); else add_new_thread (dm_obj); }); account.db.end_transaction (); } } private void add_new_thread (Json.Object dm_obj) { // {{{ int64 sender_id = dm_obj.get_int_member ("sender_id"); int64 message_id = dm_obj.get_int_member ("id"); save_message (dm_obj); if (sender_id == account.id) return; string text = dm_obj.get_string_member ("text"); if (thread_map.has_key(sender_id)) { var t_e = thread_map.get (sender_id); if (t_e.last_message_id > message_id) return; if (!user_id_visible (t_e.user_id)) { t_e.unread_count ++; } t_e.last_message = text; t_e.last_message_id = message_id; account.db.update ("dm_threads").val ("last_message", text) .vali64 ("last_message_id", message_id) .where_eqi ("user_id", sender_id).run (); t_e.notification_id = notify_new_dm (t_e, Utils.unescape_html (text)); thread_list.invalidate_sort (); return; } var urls = dm_obj.get_object_member ("entities").get_array_member ("urls"); var url_list = new TextEntity[urls.get_length ()]; urls.foreach_element((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member("expanded_url"); Json.Array indices = url.get_array_member ("indices"); expanded_url = expanded_url.replace("&", "&"); url_list[index] = TextEntity() { from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1) , display_text = url.get_string_member ("display_url") }; }); var thread_entry = new DMThreadEntry (sender_id); var author = dm_obj.get_string_member ("sender_screen_name"); string sender_name = dm_obj.get_object_member ("sender").get_string_member ("name").strip (); thread_entry.name = sender_name; thread_entry.screen_name = author; thread_entry.last_message = TextTransform.transform (text, url_list, TransformFlags.EXPAND_LINKS); thread_entry.last_message_id = message_id; thread_list.add(thread_entry); thread_list.invalidate_sort (); thread_map.set(sender_id, thread_entry); string avatar_url = dm_obj.get_object_member ("sender").get_string_member ("profile_image_url"); account.db.insert( "dm_threads") .vali64 ("user_id", sender_id) .val ("name", sender_name) .val ("screen_name", author) .val ("last_message", thread_entry.last_message) .vali64 ("last_message_id", message_id) .val ("avatar_url", avatar_url) .run (); account.user_counter.user_seen (sender_id, author, sender_name); thread_entry.avatar = Twitter.get ().get_avatar (avatar_url, (a) => { thread_entry.avatar = a; }); } // }}} private void save_message (Json.Object dm_obj) { // {{{ Json.Object sender = dm_obj.get_object_member ("sender"); Json.Object recipient = dm_obj.get_object_member ("recipient"); int64 sender_id = dm_obj.get_int_member ("sender_id"); int64 dm_id = dm_obj.get_int_member ("id"); string text = dm_obj.get_string_member ("text"); if (dm_obj.has_member ("entities")) { var urls = dm_obj.get_object_member ("entities").get_array_member ("urls"); var url_list = new TextEntity[urls.get_length ()]; urls.foreach_element((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member("expanded_url"); Json.Array indices = url.get_array_member ("indices"); expanded_url = expanded_url.replace("&", "&"); url_list[index] = TextEntity() { from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1) , target = expanded_url, display_text = url.get_string_member ("display_url") }; }); text = TextTransform.transform (text, url_list, 0); } // TODO: Update last_message account.db.insert ("dms").vali64 ("id", dm_id) .vali64 ("from_id", sender_id) .vali64 ("to_id", dm_obj.get_int_member ("recipient_id")) .val ("from_screen_name", dm_obj.get_string_member ("sender_screen_name")) .val ("to_screen_name", dm_obj.get_string_member ("recipient_screen_name")) .val ("from_name", sender.get_string_member ("name")) .val ("to_name", recipient.get_string_member ("name")) .val ("avatar_url", sender.get_string_member ("profile_image_url")) .vali64 ("timestamp", Utils.parse_date (dm_obj.get_string_member ("created_at")).to_unix ()) .val ("text", text) .run (); if (sender_id != account.id) max_received_id = dm_id; else max_sent_id = dm_id; } // }}} private void save_last_messages () { account.db.begin_transaction (); foreach (var thread_entry in thread_map.values) { account.db.update ("dm_threads").val ("last_message", thread_entry.last_message) .where_eqi ("user_id", thread_entry.user_id).run (); } account.db.end_transaction (); } private void remove_spinner () { if (progress_spinner != null && progress_spinner.parent != null) { thread_list.remove (thread_list.get_row_at_index (1)); progress_spinner = null; } } private string? notify_new_dm (DMThreadEntry thread_entry, string msg_text) { if (!Settings.notify_new_dms ()) return null; string sender_screen_name = thread_entry.screen_name; int64 sender_id = thread_entry.user_id; string id = "new-dm-" + sender_id.to_string (); string summary; string text; if (thread_entry.notification_id != null) { GLib.Application.get_default ().withdraw_notification (id); summary = ngettext ("%d new Message from %s", "%d new Messages from %s", thread_entry.unread_count).printf (thread_entry.unread_count, thread_entry.name); text = ""; } else { summary = _("New direct message from %s").printf (sender_screen_name); text = msg_text; } var n = new GLib.Notification (summary); n.set_body (text); var value = new GLib.Variant.tuple ({new GLib.Variant.int64 (account.id), new GLib.Variant.int64 (sender_id)}); n.set_default_action_and_target_value ("app.show-dm-thread", value); GLib.Application.get_default ().send_notification (id, n); return id; } public void create_tool_button(Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton(group, "corebird-dms-symbolic", _("Direct Messages")); } public Gtk.RadioButton? get_tool_button() { return tool_button; } private bool user_id_visible (int64 sender_id) { return (main_window.cur_page_id == Page.DM && ((DMPage)main_window.get_page (Page.DM)).user_id == sender_id); } public string? get_title () { return _("Direct Messages"); } public void adjust_unread_count_for_user_id (int64 user_id) { DMThreadEntry? user_entry = thread_map.get (user_id); if (user_entry == null) { warning ("No DMThreadEntry instance for id %s", user_id.to_string ()); return; } this.unread_count -= user_entry.unread_count; debug ("unread_count -= %d", user_entry.unread_count); user_entry.unread_count = 0; } public string? get_notification_id_for_user_id (int64 user_id) { DMThreadEntry? user_entry = thread_map.get (user_id); if (user_entry == null) { warning ("No DMThreadEntry instance for id %s", user_id.to_string ()); return null; } string id = user_entry.notification_id; user_entry.notification_id = null; return id; } } corebird-1.1/src/DefaultTimeline.vala000066400000000000000000000215131260276623600176670ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public abstract class DefaultTimeline : ScrollWidget, IPage, ITimeline { protected bool initialized = false; public int id { get; set; } private int _unread_count = 0; public int unread_count { set { _unread_count = value; debug ("New unread count: %d", value); tool_button.show_badge = (_unread_count > 0); } get { return this._unread_count; } } public unowned MainWindow main_window { set; get; } protected TweetListBox tweet_list { set; get; default=new TweetListBox ();} public unowned Account account { get; set; } protected BadgeRadioToolButton tool_button; protected uint tweet_remove_timeout { get; set; } private DeltaUpdater _delta_updater; public DeltaUpdater delta_updater { get { return _delta_updater; } set { this._delta_updater = value; tweet_list.delta_updater = value; } } protected abstract string function { get; } protected bool loading = false; protected Gtk.Widget? last_focus_widget = null; public DefaultTimeline (int id) { this.id = id; this.scrolled_to_start.connect(handle_scrolled_to_start); this.scrolled_to_end.connect(() => { if (!loading) { load_older (); } }); this.vadjustment.notify["value"].connect (() => { mark_seen_on_scroll (vadjustment.value); }); this.add (tweet_list); tweet_list.row_activated.connect ((row) => { if (row is TweetListEntry) { var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); } last_focus_widget = row; }); tweet_list.retry_button_clicked.connect (() => { tweet_list.model.clear (); this.load_newest (); }); this.hexpand = true; } public virtual void on_join (int page_id, Bundle? args) { if (!initialized) { load_newest (); account.user_stream.resumed.connect (stream_resumed_cb); initialized = true; } if (Settings.auto_scroll_on_new_tweets ()) { this._unread_count = 0; mark_seen (-1); } if (last_focus_widget != null) { last_focus_widget.grab_focus (); } } public bool handles_double_open () { return true; } public void double_open () { if (!loading) { this.scroll_up_next (true, false, true); tweet_list.get_row_at_index (0).grab_focus (); } } public virtual void on_leave () { Gtk.Widget? focus_widget = main_window.get_focus (); if (focus_widget == null) return; GLib.List list_rows = tweet_list.get_children (); foreach (Gtk.Widget w in list_rows) { if (w == focus_widget) { last_focus_widget = w; break; } } if (tweet_list.action_entry != null && tweet_list.action_entry.shows_actions) tweet_list.action_entry.toggle_mode (); } public abstract void load_newest (); public abstract void load_older (); public abstract string? get_title (); public override void destroy () { if (tweet_remove_timeout > 0) { GLib.Source.remove (tweet_remove_timeout); tweet_remove_timeout = 0; } } public virtual void create_tool_button(Gtk.RadioButton? group){} public Gtk.RadioButton? get_tool_button() { return tool_button; } /** * Handle the case of the user scrolling to the start of the list, * i.e. remove all the items except a few ones after a timeout. */ protected void handle_scrolled_to_start() { // {{{ if (tweet_remove_timeout != 0) return; if (tweet_list.model.get_n_items () > ITimeline.REST) { tweet_remove_timeout = GLib.Timeout.add (500, () => { if (!scrolled_up) { tweet_remove_timeout = 0; return false; } tweet_list.model.remove_last_n_visible (tweet_list.model.get_n_items () - ITimeline.REST); tweet_remove_timeout = 0; return GLib.Source.REMOVE; }); } else if (tweet_remove_timeout != 0) { GLib.Source.remove (tweet_remove_timeout); tweet_remove_timeout = 0; } } // }}} public void delete_tweet (int64 tweet_id) { bool was_seen; bool removed = this.tweet_list.model.delete_id (tweet_id, out was_seen); if (removed && !was_seen) this.unread_count --; } public void toggle_favorite (int64 id, bool mode) { // {{{ var tweets = tweet_list.get_children (); foreach (var w in tweets) { if (!(w is TweetListEntry)) continue; var t = ((TweetListEntry)w).tweet; if (t.id == id) { t.favorited = mode; break; } } } // }}} /** * So, we don't want to display a retweet in the following situations: * 1) If the original tweet was a tweet by the authenticated user * 2) In any case, if the user follows the author of the tweet * (not the author of the retweet!), we already get the source * tweet by other means, so don't display it again. * 3) It's a retweet from the authenticating user itself * 4) If the tweet was retweeted by a user that is on the list of * users the authenticating user disabled RTs for. * 5) If the retweet is already in the timeline. There's no other * way of checking the case where 2 indipendend users retweet * the same tweet. */ protected uint get_rt_flags (Tweet t) { uint flags = 0; /* First case */ if (t.user_id == account.id) flags |= Tweet.HIDDEN_FORCE; /* Second case */ if (account.follows_id (t.user_id)) flags |= Tweet.HIDDEN_RT_BY_FOLLOWEE; /* third case */ if (t.retweeted_tweet != null && t.retweeted_tweet.author.id == account.id) flags |= Tweet.HIDDEN_FORCE; /* Fourth case */ foreach (int64 id in account.disabled_rts) if (id == t.source_tweet.author.id) { flags |= Tweet.HIDDEN_RTS_DISABLED; break; } /* Fifth case */ foreach (Gtk.Widget w in tweet_list.get_children ()) { if (w is TweetListEntry) { var tt = ((TweetListEntry)w).tweet; if (tt.retweeted_tweet != null && tt.retweeted_tweet.id == t.retweeted_tweet.id) { flags |= Tweet.HIDDEN_FORCE; break; } } } return flags; } protected void mark_seen (int64 id) { foreach (Gtk.Widget w in tweet_list.get_children ()) { if (w == null || !(w is TweetListEntry)) continue; var tle = (TweetListEntry) w; if (tle.tweet.id == id || id == -1) { if (!tle.tweet.seen) { this.unread_count--; } tle.tweet.seen = true; break; } } } protected void scroll_up (Tweet t) { bool auto_scroll = Settings.auto_scroll_on_new_tweets (); if (this.scrolled_up && (t.user_id == account.id || auto_scroll)) { this.scroll_up_next (true, false, main_window.cur_page_id != this.id); } } private void stream_resumed_cb () { if (this.tweet_list.model.get_n_items () == 0) return; var call = account.proxy.new_call (); call.set_function (this.function); call.set_method ("GET"); call.add_param ("count", "1"); call.add_param ("since_id", (this.tweet_list.model.greatest_id + 1).to_string ()); call.add_param ("trim_user", "true"); call.add_param ("contributor_details", "false"); call.add_param ("include_entities", "false"); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { tweet_list.model.clear (); load_newest (); warning (e.message); return; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { tweet_list.model.clear (); load_newest (); warning (e.message); return; } var root_arr = parser.get_root ().get_array (); if (root_arr.get_length () > 0) { tweet_list.model.clear (); unread_count = 0; load_newest (); } }); } } corebird-1.1/src/DeltaUpdater.vala000066400000000000000000000053531260276623600171760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class DeltaUpdater : GLib.Object { private Gee.ArrayList> minutely = new Gee.ArrayList> (); private Gee.ArrayList> hourly = new Gee.ArrayList> (); private uint minutely_id; private uint hourly_id; public DeltaUpdater () { minutely_id = GLib.Timeout.add(60 * 1000, () => { for (int i = 0, size = minutely.size; i < size; i++) { WeakRef item_ref = minutely.get (i); ITwitterItem item = minutely.get (i).get (); if (item == null) { minutely.remove (item_ref); size --; continue; } int seconds = item.update_time_delta (); if (seconds >= 3600) { minutely.remove (item_ref); hourly.add (item_ref); size --; } } return true; }); hourly_id = GLib.Timeout.add(60 * 60 * 1000, () => { for (int i = 0, size = hourly.size; i < size; i++) { WeakRef item_ref = hourly.get (i); if (item_ref.get () == null) { hourly.remove (item_ref); size --; continue; } item_ref.get ().update_time_delta (); } return true; }); } ~DeltaUpdater() { if (minutely_id != 0) GLib.Source.remove (minutely_id); if (hourly_id != 0) GLib.Source.remove (hourly_id); } public void add (ITwitterItem entry) { // TODO: This sucks GLib.DateTime now = new GLib.DateTime.now_local (); int64 sort_factor = entry.sort_factor; // Fuck. if (entry is TweetListEntry) { var e = (TweetListEntry)entry; sort_factor = e.tweet.source_tweet.created_at; } GLib.TimeSpan diff = now.difference (new GLib.DateTime.from_unix_local (sort_factor)); int seconds = (int)(diff / 1000.0 / 1000.0); WeakRef r = new WeakRef (entry); if (seconds < 3600) minutely.add (r); else if (seconds < 60 * 60 * 24) hourly.add (r); } } corebird-1.1/src/FavoritesTimeline.vala000066400000000000000000000060621260276623600202470ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class FavoritesTimeline : IMessageReceiver, DefaultTimeline { protected override string function { get { return "1.1/favorites/list.json"; } } public FavoritesTimeline (int id, Account account) { base (id); this.account = account; this.tweet_list.account = account; } private void stream_message_received (StreamMessageType type, Json.Node root) { // {{{ if (type == StreamMessageType.EVENT_FAVORITE) { Json.Node tweet_obj = root.get_object ().get_member ("target_object"); int64 tweet_id = tweet_obj.get_object ().get_int_member ("id"); foreach (Gtk.Widget w in tweet_list.get_children ()) { if (!(w is TweetListEntry)) continue; var tle = (TweetListEntry) w; if (tle.tweet.id == tweet_id) { tle.tweet.favorited = true; return; } } Tweet tweet = new Tweet (); tweet.load_from_json (tweet_obj, new GLib.DateTime.now_local (), this.account); tweet.favorited = true; var tle = new TweetListEntry (tweet, this.main_window, this.account); this.delta_updater.add (tle); this.tweet_list.add (tle); } else if (type == StreamMessageType.EVENT_UNFAVORITE) { int64 id = root.get_object ().get_object_member ("target_object").get_int_member ("id"); toggle_favorite (id, false); } } // }}} public override void on_leave () { GLib.List children = tweet_list.get_children (); foreach (Gtk.Widget w in children) { if (!(w is TweetListEntry)) continue; if (!((TweetListEntry)w).tweet.favorited) { GLib.Idle.add(() => {tweet_list.remove (w); return false;}); } } base.on_leave (); } public override void load_newest () { this.loading = true; this.load_newest_internal.begin (() => { this.loading = false; }); } public override void load_older () { this.balance_next_upper_change (BOTTOM); this.loading = true; this.load_older_internal.begin (() => { this.loading = false; }); } public override string? get_title () { return _("Favorites"); } public override void create_tool_button (Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton(group, "starred-symbolic", _("Favorites")); } } corebird-1.1/src/Filter.vala000066400000000000000000000027471260276623600160510ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Filter : GLib.Object { public string content { get; set; } public int id { get; set; } private GLib.Regex? regex = null; public Filter (string expression) { this.reset (expression); } /** * (Re)Set the Filter's regular expression to the given one. * * @param expression The new expression. */ public void reset (string expression) { try { this.regex = new GLib.Regex (expression, GLib.RegexCompileFlags.CASELESS); } catch (GLib.RegexError e) { warning ("Regex error for `%s`: %s", expression, e.message); } this.content = expression; } public bool matches (string test_text) { if (regex == null) { return false; } return regex.match (test_text); } } corebird-1.1/src/FilterPage.vala000066400000000000000000000147461260276623600166500ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/filter-page.ui")] class FilterPage : Gtk.ScrolledWindow, IPage, IMessageReceiver { public int id { get; set; } public unowned MainWindow main_window {get; set;} public unowned Account account {get; set;} private BadgeRadioToolButton tool_button; [GtkChild] private Gtk.ListBox filter_list; [GtkChild] private Gtk.ListBox user_list; [GtkChild] private Gtk.Frame user_list_frame; private bool filters_loaded = false; private bool users_loaded = false; public FilterPage (int id, Account account) { this.id = id; this.account = account; filter_list.set_header_func (default_header_func); filter_list.add (new AddListEntry (_("Add new Filter"))); filter_list.row_activated.connect ((row) => { if (row is AddListEntry) { var dialog = new ModifyFilterDialog (main_window, account); dialog.filter_added.connect (filter_added_cb); dialog.show_all (); } else if (row is FilterListEntry) { var filter_row = (FilterListEntry) row; var dialog = new ModifyFilterDialog (main_window, account, filter_row.filter); dialog.filter_added.connect (filter_added_cb); dialog.show_all (); } }); user_list.set_header_func (default_header_func); } public void on_join (int page_id, Bundle? args) { // {{{ if (!filters_loaded) { foreach (Filter f in account.filters) { var entry = new FilterListEntry (f, account, main_window); filter_list.add (entry); } filters_loaded = true; } if (!GLib.NetworkMonitor.get_default ().get_network_available ()) return; if (users_loaded) return; var call = account.proxy.new_call (); call.set_function ("1.1/blocks/list.json"); call.set_method ("GET"); call.add_param ("include_entities", "false"); call.add_param ("skip_status", "true"); TweetUtils.load_threaded.begin (call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); return; } Json.Array users = root.get_object ().get_array_member ("users"); uint n_users = users.get_length (); users.foreach_element ((arr, index, node) => { var obj = node.get_object (); add_user (obj); }); if (n_users > 0) { user_list_frame.show (); } }); users_loaded = true; } // }}} /** * Called when the user adds a new Filter via the AddFilterDialog * **/ private void filter_added_cb (Filter f, bool created) { if (created) { var entry = new FilterListEntry (f, account, main_window); filter_list.add (entry); } else { var children = filter_list.get_children (); foreach (Gtk.Widget w in children) { if (!(w is FilterListEntry)) continue; var le = (FilterListEntry) w; if (le.filter.id == f.id) { le.content = f.content; break; } } } } public void stream_message_received (StreamMessageType type, Json.Node root_node) { if (type == StreamMessageType.EVENT_BLOCK) { var obj = root_node.get_object ().get_object_member ("target"); add_user (obj); } else if (type == StreamMessageType.EVENT_UNBLOCK) { var obj = root_node.get_object ().get_object_member ("target"); int64 user_id = obj.get_int_member ("id"); remove_user (user_id); } } private void add_user (Json.Object user_obj) { int64 id = user_obj.get_int_member ("id"); // make sure the user does not yet exist in the list remove_user (id); var entry = new UserFilterEntry (); entry.user_id = id; entry.name = user_obj.get_string_member ("name"); entry.screen_name = user_obj.get_string_member ("screen_name"); entry.avatar = user_obj.get_string_member ("profile_image_url"); entry.deleted.connect ((id) => { unblock_user (id);}); user_list.add (entry); user_list_frame.show (); } private void remove_user (int64 id) { foreach (Gtk.Widget w in user_list.get_children ()) { if (!(w is UserFilterEntry)) continue; if (((UserFilterEntry)w).user_id == id) user_list.remove (w); } if (user_list.get_children ().length () == 0) { user_list_frame.hide (); } } private void unblock_user (int64 id) { var call = account.proxy.new_call (); call.set_method ("POST"); call.set_function ("1.1/blocks/destroy.json"); call.add_param ("include_entities", "false"); call.add_param ("skip_status", "true"); call.add_param ("user_id", id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); warning (e.message); return; } }); remove_user (id); } [GtkCallback] private bool filter_list_keynav_failed_cb (Gtk.DirectionType direction) { if (direction == Gtk.DirectionType.DOWN) { if (user_list.visible) { user_list.child_focus (direction); } return true; } return false; } [GtkCallback] private bool user_list_keynav_failed_cb (Gtk.DirectionType direction) { if (direction == Gtk.DirectionType.UP) { filter_list.child_focus (direction); return true; } return false; } public void on_leave () {} public void create_tool_button (Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton(group, "corebird-filter-symbolic", _("Filters")); } public Gtk.RadioButton? get_tool_button() { return tool_button; } public string? get_title () { return _("Filters"); } } corebird-1.1/src/HomeTimeline.vala000066400000000000000000000137541260276623600172030ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class HomeTimeline : IMessageReceiver, DefaultTimeline { protected override string function { get { return "1.1/statuses/home_timeline.json"; } } public HomeTimeline(int id, Account account) { base (id); this.account = account; this.tweet_list.account = account; } public void stream_message_received (StreamMessageType type, Json.Node root) { // {{{ if (type == StreamMessageType.TWEET) { add_tweet (root); } else if (type == StreamMessageType.DELETE) { int64 id = root.get_object ().get_object_member ("delete") .get_object_member ("status").get_int_member ("id"); delete_tweet (id); } else if (type == StreamMessageType.EVENT_FAVORITE) { int64 id = root.get_object ().get_object_member ("target_object").get_int_member ("id"); int64 source_id = root.get_object ().get_object_member ("source").get_int_member ("id"); if (source_id == account.id) toggle_favorite (id, true); } else if (type == StreamMessageType.EVENT_UNFAVORITE) { int64 id = root.get_object ().get_object_member ("target_object").get_int_member ("id"); int64 source_id = root.get_object ().get_object_member ("source").get_int_member ("id"); if (source_id == account.id) toggle_favorite (id, false); } else if (type == StreamMessageType.EVENT_BLOCK) { int64 user_id = root.get_object ().get_object_member ("target").get_int_member ("id"); hide_tweets_from (user_id, Tweet.HIDDEN_AUTHOR_BLOCKED); } else if (type == StreamMessageType.EVENT_UNBLOCK) { int64 user_id = root.get_object ().get_object_member ("target").get_int_member ("id"); show_tweets_from (user_id, Tweet.HIDDEN_AUTHOR_BLOCKED); } } // }}} private void add_tweet (Json.Node obj) { // {{{ GLib.DateTime now = new GLib.DateTime.now_local (); Tweet t = new Tweet(); t.load_from_json (obj, now, account); if (t.retweeted_tweet != null) t.hidden_flags |= get_rt_flags (t); if (account.blocked_or_muted (t.user_id)) t.hidden_flags |= Tweet.HIDDEN_RETWEETER_BLOCKED; if (t.retweeted_tweet != null && account.blocked_or_muted (t.retweeted_tweet.author.id)) t.hidden_flags |= Tweet.HIDDEN_AUTHOR_BLOCKED; if (account.filter_matches (t)) t.hidden_flags |= Tweet.HIDDEN_FILTERED; bool auto_scroll = Settings.auto_scroll_on_new_tweets (); this.balance_next_upper_change (TOP); t.seen = t.user_id == account.id || (t.retweeted_tweet != null && t.retweeted_tweet.author.id == account.id) || (this.scrolled_up && main_window.cur_page_id == this.id && auto_scroll); bool should_focus = (tweet_list.get_first_visible_row ().is_focus && this.scrolled_up); tweet_list.model.add (t); if (should_focus) { tweet_list.get_first_visible_row ().grab_focus (); } if (!t.is_hidden) { base.scroll_up (t); if (!t.seen) this.unread_count ++; } // We never show any notifications if auto-scroll-on-new-tweet is enabled int stack_size = Settings.get_tweet_stack_count (); if (t.user_id == account.id || auto_scroll) return; if (stack_size == 1 && !auto_scroll) { string summary = ""; if (t.retweeted_tweet != null){ summary = _("%s retweeted %s").printf (t.source_tweet.author.user_name, t.retweeted_tweet.author.user_name); } else { summary = _("%s tweeted").printf (t.source_tweet.author.user_name); } NotificationManager.notify (account, summary, t.get_real_text (), Dirs.cache ("assets/avatars/" + Utils.get_avatar_name (t.avatar_url))); } else if(stack_size != 0 && unread_count % stack_size == 0 && unread_count > 0) { string summary = ngettext("%d new Tweet!", "%d new Tweets!", unread_count).printf (unread_count); NotificationManager.notify (account, summary); } } // }}} public void hide_tweets_from (int64 user_id, uint reason) { TweetModel tm = (TweetModel) tweet_list.model; tm.toggle_flag_on_tweet (user_id, reason, true); } public void show_tweets_from (int64 user_id, uint reason) { TweetModel tm = (TweetModel) tweet_list.model; tm.toggle_flag_on_tweet (user_id, reason, false); } public void hide_retweets_from (int64 user_id, uint reason) { TweetModel tm = (TweetModel) tweet_list.model; tm.toggle_flag_on_retweet (user_id, reason, true); } public void show_retweets_from (int64 user_id, uint reason) { TweetModel tm = (TweetModel) tweet_list.model; tm.toggle_flag_on_retweet (user_id, reason, false); } public override string? get_title () { return "@" + account.screen_name; } public override void load_newest () { this.loading = true; this.load_newest_internal.begin (() => { this.loading = false; }); } public override void load_older () { this.balance_next_upper_change (BOTTOM); this.loading = true; this.load_older_internal.begin (() => { this.loading = false; }); } public override void create_tool_button (Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton(group, "user-home-symbolic", _("Home")); } } corebird-1.1/src/IMessageReceiver.vala000066400000000000000000000016621260276623600200010ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public interface IMessageReceiver : GLib.Object { public abstract void stream_message_received (StreamMessageType type, Json.Node root_node); } corebird-1.1/src/IPage.vala000066400000000000000000000025571260276623600156100ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ /** * Page in a MainWindow(i.e. in the MainWindow's GtkStack). */ public interface IPage : Gtk.Widget { public abstract int id { get; set; } public abstract void on_join(int page_id, Bundle? args); public abstract void on_leave (); public abstract void create_tool_button(Gtk.RadioButton? group); public abstract Gtk.RadioButton? get_tool_button(); public abstract string? get_title (); public abstract unowned MainWindow main_window {get; set;} public abstract unowned Account account {get; set;} public virtual bool handles_double_open () { return false; } public virtual void double_open () {} } corebird-1.1/src/ITimeline.vala000066400000000000000000000106441260276623600164760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ /** * Describes everything a timeline should provide, in an abstract way. * Default implementations are given through the *_internal methods. */ public interface ITimeline : Gtk.Widget, IPage { public static const int REST = 25; /** The lowest id of any tweet in this timeline */ protected abstract TweetListBox tweet_list {get; set;} public abstract int unread_count {get; set;} public abstract DeltaUpdater delta_updater {get; set;} protected abstract string function {get;} /** * Default implementation for loading the newest tweets * from the given function of the twitter api. */ protected async void load_newest_internal () { //{{{ int requested_tweet_count = 28; var call = account.proxy.new_call (); call.set_function (this.function); call.set_method("GET"); call.add_param ("count", requested_tweet_count.to_string ()); call.add_param ("contributor_details", "true"); call.add_param ("include_my_retweet", "true"); call.add_param ("max_id", (tweet_list.model.lowest_id - 1).to_string ()); Json.Node? root_node = null; try { root_node = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { message (e.message); tweet_list.set_error ("%s\n%s".printf (_("Could not load tweets"), e.message)); return; } var root = root_node.get_array(); if (root.get_length () == 0) { tweet_list.set_empty (); return; } yield TweetUtils.work_array (root, tweet_list, main_window, account); } //}}} /** * Default implementation to load older tweets. * */ protected async void load_older_internal () { //{{{ int requested_tweet_count = 28; var call = account.proxy.new_call (); call.set_function (this.function); call.set_method ("GET"); call.add_param ("count", requested_tweet_count.to_string ()); call.add_param ("include_my_retweet", "true"); call.add_param ("max_id", (tweet_list.model.lowest_id - 1).to_string ()); Json.Node? root_node = null; try { root_node = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return; } var root = root_node.get_array (); if (root.get_length () == 0) { tweet_list.set_empty (); return; } yield TweetUtils.work_array (root, tweet_list, main_window, account); } ///}}} /** * Mark the TweetListEntries the user has already seen. * * @param value The scrolling value as from Gtk.Adjustment */ protected void mark_seen_on_scroll (double value) { //{{{ if (unread_count == 0) return; // We HAVE to use widgets here. tweet_list.forall_internal (false, (w) => { if (!(w is TweetListEntry)) return; var tle = (TweetListEntry)w; if (tle.tweet.seen) return; Gtk.Allocation alloc; tle.get_allocation (out alloc); if (alloc.y + (alloc.height / 2.0) >= value) { tle.tweet.seen = true; unread_count--; } }); } //}}} public void rerun_filters () { TweetModel tm = tweet_list.model; for (uint i = 0, p = tm.get_n_items (); i < p; i ++) { var tweet = (Tweet) tm.get_object (i); if (account.filter_matches (tweet)) { tweet.hidden_flags |= Tweet.HIDDEN_FILTERED; if (!tweet.seen) { this.unread_count --; tweet.seen = true; } } else { tweet.hidden_flags &= ~Tweet.HIDDEN_FILTERED; } tweet.hidden_flags_changed (); } } } corebird-1.1/src/ITwitterItem.vala000066400000000000000000000026661260276623600172160ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public interface ITwitterItem : Gtk.Widget { public static int sort_func (Gtk.ListBoxRow a, Gtk.ListBoxRow b) { if(((ITwitterItem)a).sort_factor < ((ITwitterItem)b).sort_factor) return 1; return -1; } public static int sort_func_inv (Gtk.ListBoxRow a, Gtk.ListBoxRow b) { if(((ITwitterItem)a).sort_factor < ((ITwitterItem)b).sort_factor) return -1; return 1; } public abstract int64 sort_factor { get; } /** * Updates the time delta label found in various ITwitterItem subclasses. * * @param now The current time. * * @return The seconds between the creation time and now. */ public abstract int update_time_delta (GLib.DateTime? now = null); } corebird-1.1/src/InlineMediaDownloader.vala000066400000000000000000000255431260276623600210200ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ bool is_media_candidate (string url) { if (Settings.max_media_size () < 0.001) return false; return url.has_prefix ("http://instagra.am") || url.has_prefix ("http://instagram.com/p/") || url.has_prefix ("https://instagr.am") || url.has_prefix ("https://instagram.com/p/") || (url.has_prefix ("http://i.imgur.com") && !url.has_suffix ("gifv")) || (url.has_prefix ("https://i.imgur.com") && !url.has_suffix ("gifv")) || url.has_prefix ("http://d.pr/i/") || url.has_prefix ("http://ow.ly/i/") || url.has_prefix ("http://www.flickr.com/photos/") || url.has_prefix ("https://www.flickr.com/photos/") || #if VIDEO url.has_prefix ("https://vine.co/v/") || url.has_suffix ("/photo/1") || url.has_prefix ("https://video.twimg.com/ext_tw_video/") || #endif url.has_prefix ("http://pbs.twimg.com/media/") || url.has_prefix ("http://twitpic.com/") ; } public class InlineMediaDownloader : GLib.Object { private static InlineMediaDownloader instance; private Gee.ArrayList urls_downloading = new Gee.ArrayList (); [Signal (detailed = true)] private signal void downloading (); private InlineMediaDownloader () {} public static new InlineMediaDownloader get () { if (GLib.unlikely (instance == null)) instance = new InlineMediaDownloader (); return instance; } public async void load_media (MiniTweet t, Media media) { yield load_inline_media (t, media); } public void load_all_media (MiniTweet t, Media[] medias) { foreach (Media m in medias) { load_media.begin (t, m); } } private static void mark_invalid (Media m, GLib.InputStream? in_stream = null, GLib.OutputStream? out_stream = null, GLib.OutputStream? out_stream2 = null) { GLib.FileUtils.remove (m.path); GLib.FileUtils.remove (m.thumb_path); m.invalid = true; m.loaded = true; try { if (in_stream != null) in_stream.close (); if (out_stream != null) out_stream.close (); if (out_stream2 != null) out_stream2.close (); } catch (GLib.Error e) { warning (e.message); } m.finished_loading (); } private async void load_real_url (MiniTweet t, Media media, string regex_str1, int match_index1) { var msg = new Soup.Message ("GET", media.url); SOUP_SESSION.queue_message (msg, (_s, _msg) => { string? back = (string)_msg.response_body.data; if (msg.status_code != Soup.Status.OK) { warning ("Message status: %s on %s", msg.status_code.to_string (), media.url); mark_invalid (media); return; } if (back == null) { warning ("Url '%s' returned null", media.url); mark_invalid (media); return; } try { var regex = new GLib.Regex (regex_str1, 0); MatchInfo info; regex.match (back, 0, out info); string real_url = info.fetch (match_index1); media.thumb_url = real_url; load_real_url.callback (); } catch (GLib.RegexError e) { critical ("Regex Error(%s): %s", regex_str1, e.message); } }); yield; } private async void load_inline_media (MiniTweet t, Media media) { GLib.SourceFunc callback = load_inline_media.callback; media.path = get_media_path (t, media); media.thumb_path = get_thumb_path (t, media); if (this.urls_downloading.contains (media.url)) { ulong id = 0; id = this.downloading[media.url].connect (() => { this.disconnect (id); load_inline_media.begin (t, media, () => { callback (); }); }); yield; } GLib.OutputStream thumb_out_stream = null; GLib.OutputStream media_out_stream = null; bool main_file_exists = false; try { media_out_stream = File.new_for_path (media.path).create (FileCreateFlags.NONE); } catch (GLib.Error e) { if (e is GLib.IOError.EXISTS) main_file_exists = true; else { warning (e.message); return; } } try { thumb_out_stream = File.new_for_path (media.thumb_path).create (FileCreateFlags.NONE); // If we came to this point, the above operation did not throw a GError, so // the thumbnail does not exist, right? if (main_file_exists) { var in_stream = GLib.File.new_for_path (media.path).read (); yield load_animation (t, in_stream, thumb_out_stream, media); try { in_stream.close (); thumb_out_stream.close (); } catch (GLib.Error e) { warning (e.message); } return; } } catch (GLib.Error e) { if (e is GLib.IOError.EXISTS) { if (main_file_exists) { media.thumbnail = load_surface (media.thumb_path); if (media.thumbnail == null) { warning ("'%s` couldn't be loaded from disk.", media.url); media.invalid = true; } media.loaded = true; media.finished_loading (); return; } else { // We just delete the old thumbnail and proceed GLib.FileUtils.remove (media.thumb_path); try { thumb_out_stream = File.new_for_path (media.thumb_path).create (FileCreateFlags.NONE); } catch (GLib.Error e) { critical (e.message); return; } } } else { warning (e.message); return; } } /* If we get to this point, the image was not cached on disk and we *really* need to download it. */ string url = media.url; if (url.has_prefix ("http://instagr.am") || url.has_prefix ("http://instagram.com/p/") || url.has_prefix ("https://instagr.am") || url.has_prefix ("https://instagram.com/p/") || url.has_prefix ("http://ow.ly/i/") || url.has_prefix ("https://ow.ly/i/") || url.has_prefix ("http://www.flickr.com/photos/") || url.has_prefix ("https://www.flickr.com/photos/")) { yield load_real_url (t, media, " { int64 content_length = msg.response_headers.get_content_length (); double mb = content_length / 1024.0 / 1024.0; double max = Settings.max_media_size (); if (mb > max) { debug ("Image %s won't be downloaded, %fMB > %fMB", media.thumb_url, mb, max); mark_invalid (media, null, thumb_out_stream, media_out_stream); SOUP_SESSION.cancel_message (msg, Soup.Status.CANCELLED); } else { media.length = content_length; } }); msg.got_chunk.connect ((buf) => { double percent = (double) buf.length / (double) media.length; media.percent_loaded += percent; }); assert (!this.urls_downloading.contains (media.url)); this.urls_downloading.add (media.url); SOUP_SESSION.queue_message(msg, (s, _msg) => { if (_msg.status_code != Soup.Status.OK) { debug ("Request on '%s' returned '%s'", _msg.uri.to_string (false), Soup.Status.get_phrase (_msg.status_code)); mark_invalid (media, null, thumb_out_stream, media_out_stream); this.urls_downloading.remove (media.url); callback (); return; } try { var ms = new MemoryInputStream.from_data (_msg.response_body.data, null); media_out_stream.write_all (_msg.response_body.data, null, null); media_out_stream.close (); load_animation.begin (t, ms, thumb_out_stream, media, () => { try { ms.close (); thumb_out_stream.close (); } catch (GLib.Error e) { warning (e.message); } this.urls_downloading.remove (media.url); callback (); this.downloading[media.url](); }); yield; } catch (GLib.Error e) { critical (e.message + " for MEDIA " + media.thumb_url); callback (); } }); yield; } private async void load_animation (MiniTweet t, GLib.InputStream in_stream, GLib.OutputStream thumb_out_stream, Media media) { Gdk.PixbufAnimation anim; try { anim = yield new Gdk.PixbufAnimation.from_stream_async (in_stream, null); } catch (GLib.Error e) { warning ("%s: %s", media.url, e.message); mark_invalid (media, in_stream, thumb_out_stream); return; } var pic = anim.get_static_image (); int thumb_width = (int)(600.0 / (float)t.medias.length); var thumb = Utils.slice_pixbuf (pic, thumb_width, MultiMediaWidget.HEIGHT); yield Utils.write_pixbuf_async (thumb, thumb_out_stream, "png"); media.thumbnail = Gdk.cairo_surface_create_from_pixbuf (thumb, 1, null); media.loaded = true; media.finished_loading (); } public string get_media_path (MiniTweet t, Media media) { string ext = Utils.get_file_type (media.thumb_url); ext = ext.down(); if(ext.length == 0) ext = "png"; int64 id = t.id; return Dirs.cache (@"assets/media/$(id)_$(t.author.id)_$(media.id).$(ext)"); } public string get_thumb_path (MiniTweet t, Media media) { int64 id = t.id; return Dirs.cache (@"assets/media/thumbs/$(id)_$(t.author.id)_$(media.id).png"); } } corebird-1.1/src/ListStatusesPage.vala000066400000000000000000000274411260276623600200660ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/list-statuses-page.ui")] class ListStatusesPage : ScrollWidget, IPage { public int id { get; set; } public unowned MainWindow main_window { get; set; } public unowned Account account { get; set; } public unowned DeltaUpdater delta_updater { set { this.tweet_list.delta_updater = value; } } private int64 list_id; private uint tweet_remove_timeout = 0; [GtkChild] private TweetListBox tweet_list; [GtkChild] private MaxSizeContainer max_size_container; [GtkChild] private Gtk.MenuButton delete_button; [GtkChild] private Gtk.Button edit_button; [GtkChild] private Gtk.Label description_label; [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label creator_label; [GtkChild] private Gtk.Label subscribers_label; [GtkChild] private Gtk.Label members_label; [GtkChild] private Gtk.Label created_at_label; [GtkChild] private Gtk.Stack name_stack; [GtkChild] private Gtk.Entry name_entry; [GtkChild] private Gtk.Stack description_stack; [GtkChild] private Gtk.Entry description_entry; [GtkChild] private Gtk.Stack delete_stack; [GtkChild] private Gtk.Button cancel_button; [GtkChild] private Gtk.Stack edit_stack; [GtkChild] private Gtk.Button save_button; [GtkChild] private Gtk.Stack mode_stack; [GtkChild] private Gtk.Label mode_label; [GtkChild] private Gtk.ComboBoxText mode_combo_box; [GtkChild] private Gtk.Button refresh_button; private bool loading = false; public ListStatusesPage (int id, Account account) { this.id = id; this.account = account; this.tweet_list.account = account; this.scroll_event.connect (scroll_event_cb); this.scrolled_to_end.connect (load_older); this.scrolled_to_start.connect (handle_scrolled_to_start); tweet_list.set_adjustment (this.get_vadjustment ()); } private bool scroll_event_cb (Gdk.EventScroll evt) { if (evt.delta_y < 0 && this.vadjustment.value == 0) { int inc = (int)(vadjustment.step_increment * (-evt.delta_y)); max_size_container.max_size += inc; return true; } return false; } /** * * * va_list params: * - int64 list_id - The id of the list to show * - string name - The lists's name * - bool user_list - true if the list belongs to the user, false otherwise * - string description - the lists's description * - string creator * - int subscribers_count * - int memebers_count * - int64 created_at * - string mode */ public void on_join (int page_id, Bundle? args) { // {{{ int64 list_id = args.get_int64 ("list_id"); if (list_id == 0) { list_id = this.list_id; return; // Continue } string? list_name = args.get_string ("name"); if (list_name != null) { bool user_list = args.get_bool ("user_list", false); string description = args.get_string ("description"); string creator = args.get_string ("creator"); int n_subscribers = args.get_int ("n_subscribers"); int n_members = args.get_int ("n_members"); int64 created_at = args.get_int64 ("created_at"); string mode = args.get_string ("mode"); delete_button.sensitive = user_list; edit_button.sensitive = user_list; name_label.label = list_name; description_label.label = description; creator_label.label = creator; members_label.label = "%'d".printf (n_members); subscribers_label.label = "%'d".printf (n_subscribers); created_at_label.label = new GLib.DateTime.from_unix_local (created_at).format ("%x, %X"); mode_label.label = Utils.capitalize (mode); } debug (@"Showing list with id $list_id"); if (list_id == this.list_id) { this.list_id = list_id; load_newer.begin (); } else { max_size_container.max_size = 0; this.list_id = list_id; tweet_list.model.clear (); load_newest.begin (); } } // }}} public void on_leave () {} private async void load_newest () { // {{{ tweet_list.set_unempty (); uint requested_tweet_count = 25; var call = account.proxy.new_call (); call.set_function ("1.1/lists/statuses.json"); call.set_method ("GET"); debug ("USING LIST ID %s", list_id.to_string ()); call.add_param ("list_id", list_id.to_string ()); call.add_param ("count", requested_tweet_count.to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return; } var root_array = root.get_array (); if (root_array.get_length () == 0) { tweet_list.set_empty (); return; } yield TweetUtils.work_array (root_array, tweet_list, main_window, account); } // }}} private async void load_older () { // {{{ if (loading) return; loading = true; uint requested_tweet_count = 25; var call = account.proxy.new_call (); call.set_function ("1.1/lists/statuses.json"); call.set_method ("GET"); call.add_param ("list_id", list_id.to_string ()); call.add_param ("max_id", (tweet_list.model.lowest_id -1).to_string ()); call.add_param ("count", requested_tweet_count.to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return; } var root_array = root.get_array (); yield TweetUtils.work_array (root_array, tweet_list, main_window, account); loading = false; } // }}} [GtkCallback] private void edit_button_clicked_cb () { name_stack.visible_child = name_entry; description_stack.visible_child = description_entry; delete_stack.visible_child = cancel_button; edit_stack.visible_child = save_button; mode_stack.visible_child = mode_combo_box; name_entry.text = real_list_name (); description_entry.text = description_label.label; mode_combo_box.active_id = mode_label.label; } [GtkCallback] private void cancel_button_clicked_cb () { name_stack.visible_child = name_label; description_stack.visible_child = description_label; delete_stack.visible_child = delete_button; edit_stack.visible_child = edit_button; mode_stack.visible_child = mode_label; } [GtkCallback] private void save_button_clicked_cb () { // Make everything go back to normal name_label.label = "@%s/%s".printf(creator_label.label, name_entry.get_text ()); description_label.label = description_entry.text; mode_label.label = mode_combo_box.active_id; cancel_button_clicked_cb (); edit_button.sensitive = false; delete_button.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/lists/update.json"); call.set_method ("POST"); call.add_param ("list_id", list_id.to_string ()); call.add_param ("name", real_list_name ()); call.add_param ("mode", mode_label.label.down ()); call.add_param ("description", description_label.label); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } edit_button.sensitive = true; delete_button.sensitive = true; }); } private string real_list_name () { string cur_name = name_label.label; int slash_index = cur_name.index_of ("/"); return cur_name.substring (slash_index + 1); } [GtkCallback] private void delete_confirmation_item_clicked_cb () { var call = account.proxy.new_call (); call.set_function("1.1/lists/destroy.json"); call.add_param ("list_id", list_id.to_string ()); call.set_method ("POST"); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } }); // Go back to the ListsPage and tell it to remove this list var bundle = new Bundle (); bundle.put_int ("mode", ListsPage.MODE_DELETE); bundle.put_int64 ("list_id", list_id); main_window.main_widget.switch_page (Page.LISTS, bundle); } [GtkCallback] private void refresh_button_clicked_cb () { // {{{ refresh_button.sensitive = false; load_newer.begin (() => { refresh_button.sensitive = true; }); } // }}} [GtkCallback] private void tweet_activated_cb (Gtk.ListBoxRow row) { if (row is TweetListEntry) { var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); } else warning ("row is of unknown type"); } private async void load_newer () { var call = account.proxy.new_call (); call.set_function ("1.1/lists/statuses.json"); call.set_method ("GET"); call.add_param ("list_id", list_id.to_string ()); int64 since_id = tweet_list.model.greatest_id; if (since_id < 0) since_id = 1; call.add_param ("since_id", since_id.to_string ()); try { yield call.invoke_async (null); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical (e.message); return; } var root_arr = parser.get_root ().get_array (); var now = new GLib.DateTime.now_local (); root_arr.foreach_element ((array, index, node) => { Tweet t = new Tweet (); t.load_from_json (node, now, account); TweetListEntry entry = new TweetListEntry (t, main_window, account); entry.show_all (); tweet_list.add (entry); }); } protected void handle_scrolled_to_start() { // {{{ if (tweet_remove_timeout != 0) return; GLib.List entries = tweet_list.get_children (); uint item_count = entries.length (); if (item_count > ITimeline.REST) { tweet_remove_timeout = GLib.Timeout.add (5000, () => { if (!scrolled_up) { tweet_remove_timeout = 0; return false; } while (item_count > ITimeline.REST) { tweet_list.remove (tweet_list.get_row_at_index (ITimeline.REST)); item_count--; } tweet_remove_timeout = 0; return false; }); } else if (tweet_remove_timeout != 0) { GLib.Source.remove (tweet_remove_timeout); tweet_remove_timeout = 0; } } // }}} public string? get_title () { return _("List"); } public void create_tool_button (Gtk.RadioButton? group) {} public Gtk.RadioButton? get_tool_button () {return null;} } corebird-1.1/src/ListsPage.vala000066400000000000000000000107501260276623600165100ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/lists-page.ui")] class ListsPage : IPage, ScrollWidget, IMessageReceiver { public static const int MODE_DELETE = 1; private BadgeRadioToolButton tool_button; private unowned MainWindow _main_window; public int unread_count { get; set; } public unowned MainWindow main_window { get { return _main_window; } set { user_lists_widget.main_window = value; this._main_window = value; } } public unowned Account account { get; set; } public unowned DeltaUpdater delta_updater { get; set; } public int id { get; set; } private bool inited = false; private int64 user_id; [GtkChild] private UserListsWidget user_lists_widget; public ListsPage (int id, Account account) { this.id = id; this.account = account; this.user_lists_widget.account = account; } public void on_join (int page_id, Bundle? args) { int mode = 0; if (!GLib.NetworkMonitor.get_default ().get_network_available ()) return; if (args != null) mode = args.get_int ("mode"); if (mode == 0 && !inited) { inited = true; this.user_id = account.id; load_newest.begin (); } else if (mode == MODE_DELETE) { int64 list_id = args.get_int64 ("list_id"); message (@"Deleting list with id $list_id"); user_lists_widget.remove_list (list_id); } } public void on_leave () { user_lists_widget.unreveal (); } private async void load_newest () { yield user_lists_widget.load_lists (user_id); } private void stream_message_received (StreamMessageType type, Json.Node root) { // {{{ if (type == StreamMessageType.EVENT_LIST_CREATED || type == StreamMessageType.EVENT_LIST_SUBSCRIBED) { var obj = root.get_object ().get_object_member ("target_object"); var entry = new ListListEntry.from_json_data (obj, account); user_lists_widget.add_list (entry); } else if (type == StreamMessageType.EVENT_LIST_DESTROYED || type == StreamMessageType.EVENT_LIST_UNSUBSCRIBED) { var obj = root.get_object ().get_object_member ("target_object"); int64 list_id = obj.get_int_member ("id"); user_lists_widget.remove_list (list_id); } else if (type == StreamMessageType.EVENT_LIST_UPDATED) { var obj = root.get_object ().get_object_member ("target_object"); int64 list_id = obj.get_int_member ("id"); update_list (list_id, obj); } else if (type == StreamMessageType.EVENT_LIST_MEMBER_ADDED) { var obj = root.get_object ().get_object_member ("target_object"); int64 list_id = obj.get_int_member ("id"); user_lists_widget.update_member_count (list_id, 1); } else if (type == StreamMessageType.EVENT_LIST_MEMBER_REMOVED) { var obj = root.get_object ().get_object_member ("target_object"); int64 list_id = obj.get_int_member ("id"); user_lists_widget.update_member_count (list_id, -1); } } // }}} public async TwitterList[] get_user_lists () { if (!inited) { inited = true; yield user_lists_widget.load_lists (user_id); } return user_lists_widget.get_user_lists (); } private void update_list (int64 list_id, Json.Object obj) { string name = obj.get_string_member ("full_name"); string description = obj.get_string_member ("description"); string mode = obj.get_string_member ("mode"); user_lists_widget.update_list (list_id, name, description, mode); } public void create_tool_button (Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton (group, "view-list-symbolic", _("Lists")); } public string? get_title () { return _("Lists"); } public Gtk.RadioButton? get_tool_button () { return tool_button; } } corebird-1.1/src/MainWidget.vala000066400000000000000000000152071260276623600166470ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/main-widget.ui")] public class MainWidget : Gtk.Box { private unowned Account account; private unowned Corebird app; private Gtk.RadioButton dummy_button = new Gtk.RadioButton (null); private IPage[] pages = new IPage[11]; private BundleHistory history = new BundleHistory (5); private DeltaUpdater delta_updater = new DeltaUpdater (); private bool page_switch_lock = false; private ImpostorWidget stack_impostor = new ImpostorWidget (); [GtkChild] private Gtk.Box left_box; [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.Revealer sidebar_revealer; public int cur_page_id { get { return history.current; } } public MainWidget (Account account, MainWindow parent, Corebird app) { this.account = account; this.app = app; account.init_proxy (); var acc_menu = (GLib.Menu)Corebird.account_menu; for (int i = 0; i < acc_menu.get_n_items (); i++){ int64 item_id = acc_menu.get_item_attribute_value (i, "user-id", VariantType.INT64).get_int64 (); if (item_id == account.id) { ((SimpleAction)app.lookup_action ("show-" + account.id.to_string ())).set_enabled (false); break; } } account.user_stream.start (); account.init_information.begin (); stack.add (stack_impostor); pages[0] = new HomeTimeline (Page.STREAM, account); pages[1] = new MentionsTimeline (Page.MENTIONS, account); pages[2] = new FavoritesTimeline (Page.FAVORITES, account); pages[3] = new DMThreadsPage (Page.DM_THREADS, account); pages[4] = new ListsPage (Page.LISTS, account); pages[5] = new FilterPage (Page.FILTERS, account); pages[6] = new SearchPage (Page.SEARCH, account); pages[7] = new ProfilePage (Page.PROFILE, account); pages[8] = new TweetInfoPage (Page.TWEET_INFO, account); pages[9] = new DMPage (Page.DM, account); pages[10] = new ListStatusesPage (Page.LIST_STATUSES, account); /* Initialize all containers */ for (int i = 0; i < pages.length; i++) { IPage page = pages[i]; page.main_window = parent; if (page is IMessageReceiver) account.user_stream.register ((IMessageReceiver)page); page.create_tool_button (dummy_button); stack.add (page); if (page.get_tool_button () != null) { left_box.add (page.get_tool_button ()); page.get_tool_button ().clicked.connect (() => { if (page.get_tool_button ().active && !page_switch_lock) { switch_page (page.id); } }); } if (!(page is ITimeline)) continue; ITimeline tl = (ITimeline)page; tl.delta_updater = delta_updater; } // TODO: Gnarf this sucks // SearchPage still needs a delta updater ((SearchPage)pages[Page.SEARCH]).delta_updater = this.delta_updater; ((DMThreadsPage)pages[Page.DM_THREADS]).delta_updater = this.delta_updater; ((DMPage)pages[Page.DM]).delta_updater = this.delta_updater; ((ProfilePage)pages[Page.PROFILE]).delta_updater = this.delta_updater; ((ListStatusesPage)pages[Page.LIST_STATUSES]).delta_updater = this.delta_updater; ((TweetInfoPage)pages[Page.TWEET_INFO]).delta_updater = this.delta_updater; Settings.get ().bind ("sidebar-visible", sidebar_revealer, "reveal-child", SettingsBindFlags.DEFAULT); } /** * Switches the window's main notebook to the given page. * * @param page_id The id of the page to switch to. * See the Page.* constants. * */ public void switch_page (int page_id, Bundle? args = null) { // {{{ if (page_id == history.current) { if (pages[page_id].handles_double_open ()) pages[page_id].double_open (); if ((history.current_bundle != null && history.current_bundle.equals (args)) || history.current_bundle == args) return; } bool push = true; // Set the correct transition type if (page_id == Page.PREVIOUS || page_id < history.current) stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT; else if (page_id == Page.NEXT || page_id > history.current) stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT; int current_page = history.current; // If we go forward/back, we don't need to update the history. if (page_id == Page.PREVIOUS) { if (history.at_start ()) return; push = false; page_id = history.back (); args = history.current_bundle; } else if (page_id == Page.NEXT) { if (history.at_end ()) return; push = false; page_id = history.forward (); args = history.current_bundle; } if (page_id == current_page) { stack_impostor.clone (pages[page_id]); var transition_type = stack.transition_type; stack.transition_type = Gtk.StackTransitionType.NONE; stack.set_visible_child (stack_impostor); stack.transition_type = transition_type; } if (history.current != -1) pages[history.current].on_leave (); if (push) { history.push (page_id, args); } /* XXX The following will cause switch_page to be called twice because setting the active property of the button will cause the clicked event to be emitted, which will call switch_page. */ IPage page = pages[page_id]; Gtk.ToggleButton button = page.get_tool_button (); page_switch_lock = true; if (button != null) button.active = true; else dummy_button.active = true; page.on_join (page_id, args); stack.set_visible_child (pages[page_id]); if (page.get_title () != null) ((MainWindow)this.parent).set_title (page.get_title ()); page_switch_lock = false; ((MainWindow)this.parent).back_button.sensitive = !history.at_start (); } // }}} public IPage get_page (int page_id) { return pages[page_id]; } public void stop () { account.uninit (); } } corebird-1.1/src/MainWindow.vala000066400000000000000000000343021260276623600166700ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/main-window.ui")] public class MainWindow : Gtk.ApplicationWindow { private const GLib.ActionEntry[] win_entries = { {"compose-tweet", show_hide_compose_window}, {"toggle-sidebar", Settings.toggle_sidebar_visible}, {"switch-page", simple_switch_page, "i"}, {"show-account-dialog", show_account_dialog}, {"show-account-list", show_account_list} }; [GtkChild] private Gtk.HeaderBar headerbar; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.ListBox account_list; [GtkChild] private Gtk.Popover account_popover; [GtkChild] private Gtk.Box header_box; [GtkChild] private Gtk.ToggleButton account_button; [GtkChild] public Gtk.Button back_button; [GtkChild] public Gtk.ToggleButton compose_tweet_button; private Gtk.MenuButton app_menu_button = null; public MainWidget main_widget; public unowned Account? account {public get; private set;} private ComposeTweetWindow? compose_tweet_window = null; public int cur_page_id { get { return main_widget.cur_page_id; } } public MainWindow (Gtk.Application app, Account? account = null){ set_default_size (480, 700); change_account (account, app); account_list.set_sort_func (account_sort_func); account_list.set_header_func (default_header_func); var add_entry = new AddListEntry (_("Add new Account")); add_entry.show_all (); account_list.add (add_entry); foreach (Account acc in Account.list_accounts ()) { if (acc.screen_name == Account.DUMMY) continue; var e = new UserListEntry.from_account (acc); e.show_settings = true; e.action_clicked.connect (() => { account_popover.hide ();}); account_list.add (e); } ((Corebird)app).account_added.connect ((new_acc) => { var entries = account_list.get_children (); foreach (Gtk.Widget ule in entries) if (ule is UserListEntry && new_acc.screen_name == ((UserListEntry)ule).screen_name) return; var ule = new UserListEntry.from_account (new_acc); ule.show_settings = true; ule.action_clicked.connect (() => { account_popover.hide ();}); account_list.add (ule); ule.show (); }); ((Corebird)app).account_removed.connect ((acc) => { var entries = account_list.get_children (); foreach (Gtk.Widget ule in entries) if (ule is UserListEntry && acc.screen_name == ((UserListEntry)ule).screen_name) { account_list.remove (ule); break; } }); this.add_action_entries (win_entries, this); headerbar.key_press_event.connect ((evt) => { if (evt.keyval == Gdk.Key.Down && main_widget != null) { main_widget.get_page (main_widget.cur_page_id).focus (Gtk.DirectionType.RIGHT); return true; } return false; }); add_accels(); load_geometry (); } /** * Adds the accelerators to the GtkWindow */ private void add_accels() { // {{{ Gtk.AccelGroup ag = new Gtk.AccelGroup(); ag.connect (Gdk.Key.Left, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_widget.switch_page (Page.PREVIOUS); return true;}); ag.connect (Gdk.Key.Right, Gdk.ModifierType.MOD1_MASK, Gtk.AccelFlags.LOCKED, () => {main_widget.switch_page (Page.NEXT); return true;}); ag.connect (Gdk.Key.Back, 0, Gtk.AccelFlags.LOCKED, () => {main_widget.switch_page (Page.PREVIOUS); return true;}); ag.connect (Gdk.Key.Forward, 0, Gtk.AccelFlags.LOCKED, () => {main_widget.switch_page (Page.NEXT); return true;}); this.add_accel_group(ag); } // }}} [GtkCallback] private void back_button_clicked_cb () { main_widget.switch_page (Page.PREVIOUS); } public void change_account (Account? account, GLib.Application app = GLib.Application.get_default ()) { int64? old_user_id = null; if (this.account != null) { old_user_id = this.account.id; this.account.info_changed.disconnect (account_info_changed); this.set_account_app_menu_sensitivity (true); } this.account = account; if (main_widget != null) { main_widget.stop (); } if (get_child () != null) { remove (get_child ()); } if (!header_box.visible) { header_box.visible = true; } Corebird cb = (Corebird) app; if (account != null && account.screen_name != Account.DUMMY) { main_widget = new MainWidget (account, this, cb); main_widget.show_all (); this.add (main_widget); main_widget.switch_page (0); this.set_title (main_widget.get_page (0).get_title ()); avatar_image.surface = account.avatar_small; account.notify["avatar-small"].connect(() => { avatar_image.surface = account.avatar_small; }); this.set_account_app_menu_sensitivity (false); account.info_changed.connect (account_info_changed); cb.account_window_changed (old_user_id, account.id); if (!Gtk.Settings.get_default ().gtk_shell_shows_app_menu) { if (app_menu_button == null) { app_menu_button = new Gtk.MenuButton (); app_menu_button.image = new Gtk.Image.from_icon_name ("emblem-system-symbolic", Gtk.IconSize.MENU); app_menu_button.get_style_context ().add_class ("image-button"); app_menu_button.menu_model = ((Gtk.Application)app).app_menu; headerbar.pack_end (app_menu_button); } else app_menu_button.show (); } } else { /* "Special case" when creating a new account */ header_box.hide (); if (app_menu_button != null) app_menu_button.hide (); Account acc_; if (account == null) acc_ = new Account (0, Account.DUMMY, "name"); else acc_ = account; this.account = acc_; this.set_title (_("Corebird")); Account.add_account (acc_); var create_widget = new AccountCreateWidget (acc_, cb); create_widget.result_received.connect ((result, acc) => { if (result) { change_account (acc); } else { //Account.remove ("screen_name"); } }); this.add (create_widget); } } [GtkCallback] private void account_row_activated_cb (Gtk.ListBoxRow row) { if (row is AddListEntry) { account_popover.hide (); Account dummy_acc = new Account (0, Account.DUMMY, "name"); var window = new MainWindow (application, dummy_acc); get_application ().add_window (window); window.show_all (); return; } var e = (UserListEntry)row; int64 user_id = e.user_id; Corebird cb = (Corebird)this.get_application (); if (user_id == this.account.id || cb.is_window_open_for_user_id (user_id)) { account_popover.hide (); return; } Account? acc = Account.query_account_by_id (user_id); if (acc != null) { change_account (acc); account_popover.hide (); } else warning ("account == null"); } [GtkCallback] private bool button_press_event_cb (Gdk.EventButton evt) { if (evt.button == 9) { // Forward thumb button main_widget.switch_page (Page.NEXT); return true; } else if (evt.button == 8) { // backward thumb button main_widget.switch_page (Page.PREVIOUS); return true; } return false; } private void show_hide_compose_window () { if (compose_tweet_window == null) { compose_tweet_window = new ComposeTweetWindow (this, account, null, ComposeTweetWindow.Mode.NORMAL); compose_tweet_window.show (); compose_tweet_window.hide.connect (() => { compose_tweet_button.active = false; }); compose_tweet_window.destroy.connect (() => { compose_tweet_window = null; }); } else { compose_tweet_window.hide (); compose_tweet_window.destroy (); } } /** * GSimpleActionActivateCallback version of switch_page, used * for keyboard accelerators. */ private void simple_switch_page (GLib.SimpleAction a, GLib.Variant? param) { main_widget.switch_page (param.get_int32 ()); } /* result of the show-account-dialog GAction */ private void show_account_dialog () { if (this.account == null || this.account.screen_name == Account.DUMMY) return; var dialog = new AccountDialog (this.account); dialog.set_transient_for (this); dialog.modal = true; dialog.show (); } /* for show-account-list GAction */ private void show_account_list () { if (this.account != null && this.account.screen_name != Account.DUMMY) this.account_popover.show (); } public IPage get_page (int page_id) { return main_widget.get_page (page_id); } [GtkCallback] private void account_button_clicked_cb () { account_popover.visible = !account_popover.visible; } [GtkCallback] private void account_popover_closed_cb () { account_button.active = false; account_popover.hide (); } [GtkCallback] private bool window_delete_cb (Gdk.EventAny evt) { if (main_widget != null) main_widget.stop (); if (account == null) return false; unowned GLib.List ws = this.application.get_windows (); debug("Windows: %u", ws.length ()); // Enable the account's entry in the app menu again set_account_app_menu_sensitivity (true); string[] startup_accounts = Settings.get ().get_strv ("startup-accounts"); if (startup_accounts.length == 1 && startup_accounts[0] == "") startup_accounts.resize (0); save_geometry (); if (startup_accounts.length > 0) return false; int n_main_windows = 0; foreach (Gtk.Window win in ws) if (win is MainWindow && ((MainWindow) win).account != null && ((MainWindow) win).account.screen_name != Account.DUMMY) n_main_windows ++; if (n_main_windows == 1) { // This is the last window so we save this one anyways... string[] new_startup_accounts = new string[1]; new_startup_accounts[0] = ((MainWindow)ws.nth_data (0)).account.screen_name; Settings.get ().set_strv ("startup-accounts", new_startup_accounts); debug ("Saving the account %s", ((MainWindow)ws.nth_data (0)).account.screen_name); } return false; } private void account_info_changed (string screen_name, string name, Cairo.Surface small_avatar, Cairo.Surface avatar) { this.set_title (main_widget.get_page (main_widget.cur_page_id).get_title ()); } /** * */ private void load_geometry () { if (account == null) { debug ("Could not load geometry, account == null"); return; } GLib.Variant win_geom = Settings.get ().get_value ("window-geometry"); int x = 0, y = 0, w = 0, h = 0; if (!win_geom.lookup (account.screen_name, "(iiii)", &x, &y, &w, &h)) { warning ("Couldn't load window geometry for screen_name `%s'", account.screen_name); return; } if (w == 0 || h == 0) return; move (x, y); resize (w, h); } /** * Saves this window's geometry in the window-geometry gsettings key. */ public void save_geometry () { if (account == null || account.screen_name == Account.DUMMY) return; GLib.Variant win_geom = Settings.get ().get_value ("window-geometry"); GLib.Variant new_geom; GLib.VariantBuilder builder = new GLib.VariantBuilder (new GLib.VariantType("a{s(iiii)}")); var iter = win_geom.iterator (); string key = null; int x = 0, y = 0, w = 0, h = 0; while (iter.next ("{s(iiii)}", &key, &x, &y, &w, &h)) { if (key != account.screen_name) { builder.add ("{s(iiii)}", key, x, y, w, h); } key = null; // Otherwise we leak key } /* Finally, add this window */ get_position (out x, out y); w = get_allocated_width (); h = get_allocated_height (); builder.add ("{s(iiii)}", account.screen_name, x, y, w, h); new_geom = builder.end (); debug ("Saving geomentry for %s: %d,%d,%d,%d", account.screen_name, x, y, w, h); Settings.get ().set_value ("window-geometry", new_geom); } private int account_sort_func (Gtk.ListBoxRow a, Gtk.ListBoxRow b) { if (a is AddListEntry) return 1; return ((UserListEntry)a).screen_name.ascii_casecmp (((UserListEntry)b).screen_name); } public void rerun_filters () { /* We only do this for stream + mentions at the moment */ ((ITimeline)get_page (Page.STREAM)).rerun_filters (); ((ITimeline)get_page (Page.MENTIONS)).rerun_filters (); } private void set_account_app_menu_sensitivity (bool sensitivity) { var acc_menu = (GLib.Menu)Corebird.account_menu; string ref_action_name = "app.show-" + account.id.to_string (); Gtk.Application app = (Gtk.Application)GLib.Application.get_default (); for (int i = 0; i < acc_menu.get_n_items (); i++) { GLib.Variant action_name = acc_menu.get_item_attribute_value (i, GLib.Menu.ATTRIBUTE_ACTION, GLib.VariantType.STRING); if (ref_action_name == action_name.get_string ()) { GLib.SimpleAction? action = (GLib.SimpleAction)app.lookup_action (ref_action_name.substring (4)); if (action != null) { action.set_enabled (sensitivity); return; } } // Glorious } // Fucking } // BRACES } corebird-1.1/src/Makefile.am000066400000000000000000000074631260276623600160130ustar00rootroot00000000000000 AM_CPPFLAGS = $(CB_CFLAGS) \ -Wno-format-security \ -Wno-unused-value AUTOMAKE_OPTIONS = subdir-objects BUILT_SOURCES = libcorebird_la_vala.stamp bin_PROGRAMS = corebird noinst_LTLIBRARIES = libcorebird.la # Sources {{{ cb_sources = \ Corebird.vala \ MainWindow.vala \ MainWidget.vala \ Account.vala \ HomeTimeline.vala \ MentionsTimeline.vala \ SearchPage.vala \ DMPage.vala \ DeltaUpdater.vala \ ITwitterItem.vala \ UserStream.vala \ IMessageReceiver.vala \ ITimeline.vala \ Tweet.vala \ IPage.vala \ UserCounter.vala \ DefaultTimeline.vala \ DMThreadsPage.vala \ InlineMediaDownloader.vala \ Settings.vala \ NotificationManager.vala \ Twitter.vala \ ProfilePage.vala \ TweetInfoPage.vala \ ListStatusesPage.vala \ ListsPage.vala \ FavoritesTimeline.vala \ Filter.vala \ FilterPage.vala \ Media.vala \ UserEventReceiver.vala \ SnippetManager.vala \ widgets/TweetListBox.vala \ widgets/MaxSizeContainer.vala \ widgets/ScrollWidget.vala \ widgets/TextButton.vala \ widgets/DoubleTapButton.vala \ widgets/ReplyEntry.vala \ widgets/PixbufButton.vala \ widgets/BadgeRadioToolButton.vala \ widgets/DMPlaceholderBox.vala \ widgets/AccountCreateWidget.vala \ widgets/AspectImage.vala \ widgets/UserListsWidget.vala \ widgets/ReplyIndicator.vala \ widgets/MultiMediaWidget.vala \ widgets/AvatarWidget.vala \ widgets/AvatarBannerWidget.vala \ widgets/MediaImageWidget.vala \ widgets/MediaVideoWidget.vala \ widgets/CropWidget.vala \ widgets/AddImageButton.vala \ widgets/CompletionTextView.vala \ widgets/LazyMenuButton.vala \ widgets/ImpostorWidget.vala \ widgets/FollowButton.vala \ util/TweetUtils.vala \ util/Utils.vala \ util/BundleHistory.vala \ util/UserCompletion.vala \ util/Config.vala \ util/WeakRef.vala \ util/Dirs.vala \ util/Bundle.vala \ util/TextTransform.vala \ util/UserUtils.vala \ list/TweetListEntry.vala \ list/DMListEntry.vala \ list/UserListEntry.vala \ list/DMThreadEntry.vala \ list/StartConversationEntry.vala \ list/ListListEntry.vala \ list/NewListEntry.vala \ list/FilterListEntry.vala \ list/UserFilterEntry.vala \ list/AddListEntry.vala \ list/ProgressEntry.vala \ list/SnippetListEntry.vala \ window/ComposeTweetWindow.vala \ window/SettingsDialog.vala \ window/UserListDialog.vala \ window/ModifyFilterDialog.vala \ window/AboutDialog.vala \ window/AccountDialog.vala \ window/MediaDialog.vala \ window/ImageCropDialog.vala \ window/ModifySnippetDialog.vala \ sql/Database.vala \ sql/Statement.vala \ sql/UpdateStatement.vala \ sql/SelectStatement.vala \ async/Collect.vala \ model/TweetModel.vala # }}} corebird.vapi libcorebird_la_vala.stamp corebird.h: $(cb_sources) @$(VALAC) $^ --vapi=corebird.vapi -C --header corebird.h @CB_VALA_FLAGS@ touch corebird.vapi libcorebird_la_vala.stamp corebird.h #corebird.h corebird.vapi: libcorebird_la_vala.stamp libcorebird_la_LIBADD = @CB_LIBS@ libcorebird_la_VALASOURCES = $(cb_sources) libcorebird_la_SOURCES = libcorebird_la_vala.stamp \ $(cb_sources:.vala=.c) corebird_SOURCES = main.vala resources.c corebird_LDADD = libcorebird.la @CB_LIBS@ corebird_VALAFLAGS = corebird.vapi @CB_VALA_FLAGS@ main.vala: corebird.vapi corebird.h GRESDEPS = $(top_srcdir)/$1 $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies --sourcedir=$(top_srcdir) $(top_srcdir)/$1) resource_deps = $(call GRESDEPS,resources.xml) resources.c: $(resource_deps) $(GLIB_COMPILE_RESOURCES) $(top_srcdir)/resources.xml --target=resources.c --generate-source --sourcedir=$(top_srcdir) CLEANFILES = *.h *.c *.o *.stamp resources.c libcorebird.la corebird corebird.vapi corebird.h EXTRA_DIST = $(cb_sources) \ corebird.h corebird-1.1/src/Media.vala000066400000000000000000000044061260276623600156350ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public enum MediaType { IMAGE, VINE, GIF, ANIMATED_GIF, TWITTER_VIDEO, UNKNOWN } public class Media : GLib.Object{ public int64 id; public string path; public string thumb_path; public string url; private string? _thumb_url = null; public string thumb_url { get { return _thumb_url ?? url; } set { _thumb_url = value; } } private string _target_url; public string target_url { get { return _target_url ?? url; } set { _target_url = value; } } public int64 length { get; set; default = 0; } public double percent_loaded { get; set; default = 0; } public MediaType type; public Cairo.Surface? thumbnail = null; /** If this media is fully downloaded and thumb is available */ public bool loaded = false; public bool invalid = false; public signal void finished_loading (); public static MediaType type_from_string (string s) { if (s == "photo") return MediaType.IMAGE; return MediaType.UNKNOWN; } /** * Returns the type of a media based on its URL. * Do not call this unless you used InlineMediaDownloader.is_media_candidate * before. * * @param url The url to check * * @return The media type */ public static MediaType type_from_url (string url) { if (url.has_prefix ("https://vine.co/v/")) return MediaType.VINE; if (url.has_suffix ("/photo/1")) return MediaType.ANIMATED_GIF; if (url.down ().has_suffix (".gif")) return MediaType.GIF; return MediaType.IMAGE; } } corebird-1.1/src/MentionsTimeline.vala000066400000000000000000000110361260276623600200760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class MentionsTimeline : IMessageReceiver, DefaultTimeline { protected override string function { get { return "1.1/statuses/mentions_timeline.json"; } } public MentionsTimeline(int id, Account account) { base (id); this.account = account; this.tweet_list.account= account; } private void stream_message_received (StreamMessageType type, Json.Node root){ if (type == StreamMessageType.TWEET) { add_tweet (root); } else if (type == StreamMessageType.DELETE) { int64 id = root.get_object ().get_object_member ("delete") .get_object_member ("status").get_int_member ("id"); delete_tweet (id); } else if (type == StreamMessageType.EVENT_FAVORITE) { int64 id = root.get_object ().get_object_member ("target_object").get_int_member ("id"); toggle_favorite (id, true); } else if (type == StreamMessageType.EVENT_UNFAVORITE) { int64 id = root.get_object ().get_object_member ("target_object").get_int_member ("id"); toggle_favorite (id, false); } } private void add_tweet (Json.Node root_node) { // {{{ /* Mark tweets as seen the user has already replied to */ var root = root_node.get_object (); var author = root.get_object_member ("user"); if (author.get_int_member ("id") == account.id && !root.get_null_member ("in_reply_to_status_id")) { mark_seen (root.get_int_member ("in_reply_to_status_id")); return; } if (root.get_string_member ("text").contains ("@" + account.screen_name)) { GLib.DateTime now = new GLib.DateTime.now_local (); Tweet t = new Tweet (); t.load_from_json (root_node, now, account); if (t.user_id == account.id) return; if (t.retweeted_tweet != null && get_rt_flags (t) > 0) return; if (account.filter_matches (t)) return; if (account.blocked_or_muted (t.user_id)) return; t.seen = false; this.balance_next_upper_change (TOP); tweet_list.model.add (t); base.scroll_up (t); this.unread_count ++; if (Settings.notify_new_mentions ()) { string text; if (t.retweeted_tweet != null) text = t.retweeted_tweet.text; else text = t.source_tweet.text; t.notification_id = send_notification (t.screen_name, t.id, Utils.unescape_html (text)); } } } // }}} /** * @return The notification's ID */ private string send_notification (string sender_screen_name, int64 tweet_id, string text) { var n = new GLib.Notification (_("New Mention from @%s") .printf (sender_screen_name)); n.set_body (text); var value = new GLib.Variant.tuple ({new GLib.Variant.string (account.screen_name), new GLib.Variant.int64 (tweet_id)}); //n.add_button_with_target_value (_("Mark read"), "app.mark-seen", value); n.set_default_action_and_target_value ("app.show-window", account.id); string id = "new-dm-" + tweet_id.to_string (); GLib.Application.get_default ().send_notification (id, n); return id; } public override void load_newest () { this.loading = true; this.load_newest_internal.begin (() => { this.loading = false; }); } public override void load_older () { if (!initialized) return; this.balance_next_upper_change (BOTTOM); this.loading = true; this.load_older_internal.begin (() => { this.loading = false; }); } public override string? get_title () { return _("Mentions"); } public override void create_tool_button (Gtk.RadioButton? group) { tool_button = new BadgeRadioToolButton(group, "corebird-mentions-symbolic", _("Mentions")); } } corebird-1.1/src/NotificationManager.vala000066400000000000000000000030211260276623600205270ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace NotificationManager { public void notify (Account acc, string summary, string body = "", string? icon = null) { var n = new GLib.Notification (summary); n.set_body (body); if (icon != null) { try { var gicon = GLib.Icon.new_for_string (icon); n.set_icon (gicon); } catch (GLib.Error e) { warning (e.message); } } /* Default action: just bring the appropriate window to front */ n.set_default_action_and_target_value ("app.show-window", acc.id); GLib.Application.get_default ().send_notification (null, n); } public void withdraw (string notification_id) { GLib.Application.get_default ().withdraw_notification (notification_id); } } corebird-1.1/src/ProfilePage.vala000066400000000000000000000724431260276623600170210ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/profile-page.ui")] class ProfilePage : ScrollWidget, IPage, IMessageReceiver { private const GLib.ActionEntry[] action_entries = { {"write-dm", write_dm_activated}, {"tweet-to", tweet_to_activated}, {"add-remove-list", add_remove_list_activated}, }; public int unread_count { get{return 0;} set{} } private unowned MainWindow _main_window; public unowned MainWindow main_window { get { return _main_window; } set { this._main_window = value; user_lists.main_window = value; } } public unowned Account account { get; set; } public int id { get; set; } public unowned DeltaUpdater delta_updater { set { tweet_list.delta_updater = value; } } [GtkChild] private AspectImage banner_image; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private Gtk.Label description_label; [GtkChild] private Gtk.Label url_label; [GtkChild] private Gtk.Label tweets_label; [GtkChild] private Gtk.Label following_label; [GtkChild] private Gtk.Label followers_label; [GtkChild] private Gtk.Label location_label; [GtkChild] private FollowButton follow_button; [GtkChild] private TweetListBox tweet_list; [GtkChild] private TweetListBox followers_list; [GtkChild] private TweetListBox following_list; [GtkChild] private Gtk.Spinner progress_spinner; [GtkChild] private Gtk.Label follows_you_label; [GtkChild] private UserListsWidget user_lists; [GtkChild] private Gtk.Stack user_stack; [GtkChild] private Gtk.MenuButton more_button; [GtkChild] private Gtk.Stack loading_stack; [GtkChild] private Gtk.RadioButton tweets_button; private GLib.MenuModel more_menu; private int64 user_id; private new string name; private string screen_name; private string avatar_url; private int follower_count = -1; private GLib.Cancellable data_cancellable; private bool lists_page_inited = false; private bool block_item_blocked = false; private bool retweet_item_blocked = false; private bool tweets_loading = false; private bool followers_loading = false; private Cursor? followers_cursor = null; private bool following_loading = false; private Cursor? following_cursor = null; private GLib.SimpleActionGroup actions; public ProfilePage (int id, Account account) { this.id = id; this.account = account; this.user_lists.account = account; this.tweet_list.account = account; this.scroll_event.connect ((evt) => { if (evt.delta_y < 0 && this.vadjustment.value == 0) { if (banner_image.scale >= 1.0) { banner_image.scale = 1.0f; return false; } banner_image.scale += 0.25f * (-evt.delta_y); return true; } return false; }); this.scrolled_to_end.connect (() => { if (user_stack.visible_child == tweet_list) { this.load_older_tweets.begin (); } else if (user_stack.visible_child == followers_list) { this.load_followers.begin (); } else if (user_stack.visible_child == following_list) { this.load_following.begin (); } }); tweet_list.row_activated.connect ((row) => { var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); }); followers_list.row_activated.connect ((row) => { var bundle = new Bundle (); bundle.put_int64 ("user_id", ((UserListEntry)row).user_id); main_window.main_widget.switch_page (Page.PROFILE, bundle); }); following_list.row_activated.connect ((row) => { var bundle = new Bundle (); bundle.put_int64 ("user_id", ((UserListEntry)row).user_id); main_window.main_widget.switch_page (Page.PROFILE, bundle); }); user_lists.hide_user_list_entry (); actions = new GLib.SimpleActionGroup (); actions.add_action_entries (action_entries, this); GLib.SimpleAction block_action = new GLib.SimpleAction.stateful ("toggle-blocked", null, new GLib.Variant.boolean (false)); block_action.activate.connect (toggle_blocked_activated); actions.add_action (block_action); GLib.SimpleAction rt_action = new GLib.SimpleAction.stateful ("toggle-retweets", null, new GLib.Variant.boolean (false)); rt_action.activate.connect (retweet_action_activated); actions.add_action (rt_action); this.insert_action_group ("user", actions); this.more_menu = more_button.menu_model; } private void set_user_id (int64 user_id) { // {{{ this.user_id = user_id; follow_button.sensitive = (user_id != account.id); ((SimpleAction)actions.lookup_action ("add-remove-list")).set_enabled (user_id != account.id); ((SimpleAction)actions.lookup_action ("write-dm")).set_enabled (user_id != account.id); ((SimpleAction)actions.lookup_action ("toggle-blocked")).set_enabled (user_id != account.id); /* We (maybe) re-enable this later when the friendship object has arrived */ ((SimpleAction)actions.lookup_action ("toggle-retweets")).set_enabled (false); load_banner (null); load_friendship.begin (); bool data_in_db = false; //Load cached data Corebird.db.select ("profiles").cols ("id", "screen_name", "name", "description", "tweets", "following", "followers", "avatar_name", "banner_url", "url", "location", "is_following") .where_eqi ("id", user_id) .run ((vals) => { /* If we get inside this block, there is already some data in the DB we can use. */ avatar_image.surface = load_surface (Dirs.cache ("/assets/avatars/" + vals[7])); var entities = new TextEntity[0]; set_data(vals[2], vals[1], vals[9], vals[10], vals[3], int.parse (vals[4]), int.parse (vals[5]), int.parse (vals[6]), vals[7], false, ref entities); this.follow_button.following = bool.parse (vals[11]); this.follow_button.sensitive = (this.user_id != this.account.id); string banner_name = Utils.get_banner_name (user_id); if (FileUtils.test(Dirs.cache("assets/banners/"+banner_name), FileTest.EXISTS)){ debug ("Banner exists, set it directly..."); load_banner (Dirs.cache ("assets/banners/" + banner_name)); } else { // TODO: ??? // If the cached banner does somehow not exist, load it again. debug("Banner %s does not exist, load it first...", banner_name); load_banner (null); } data_in_db = true; return false; }); /* Load the profile data now, then - if available - set the cached data */ load_profile_data.begin (user_id, !data_in_db); } // }}} private async void load_friendship () { Friendship? fr = yield UserUtils.load_friendship (account, this.user_id); follows_you_label.visible = fr.followed_by; set_user_blocked (fr.blocking); set_retweets_disabled (fr.following && !fr.want_retweets); ((SimpleAction)actions.lookup_action ("toggle-retweets")).set_enabled (fr.following); } private async void load_profile_data (int64 user_id, bool show_spinner) { //{{{ if (show_spinner) { loading_stack.visible_child_name = "progress"; progress_spinner.start (); } follow_button.sensitive = false; var call = account.proxy.new_call (); call.set_method ("GET"); call.set_function ("1.1/users/show.json"); call.add_param ("user_id", user_id.to_string ()); call.add_param ("include_entities", "false"); Json.Node? root_node = null; try { root_node = yield TweetUtils.load_threaded (call); // TODO: Use data_cancellable here } catch (GLib.Error e) { warning (e.message); return; } var root = root_node.get_object(); int64 id = root.get_int_member ("id"); string avatar_url = root.get_string_member("profile_image_url"); avatar_url = avatar_url.replace("_normal", "_bigger"); string avatar_name = Utils.get_avatar_name(avatar_url); avatar_image.surface = Twitter.get ().get_avatar (avatar_url, (a) => { avatar_image.surface = a; if (show_spinner) { progress_spinner.stop (); loading_stack.visible_child_name = "data"; } }, 73); if (avatar_image.surface != null && show_spinner) { progress_spinner.stop (); loading_stack.visible_child_name = "data"; } string name = root.get_string_member("name").replace ("&", "&").strip (); string screen_name = root.get_string_member("screen_name"); string description = root.get_string_member("description").replace("&", "&"); int followers = (int)root.get_int_member("followers_count"); int following = (int)root.get_int_member("friends_count"); int tweets = (int)root.get_int_member("statuses_count"); bool is_following = false; if (Utils.usable_json_value (root, "following")) is_following = root.get_boolean_member("following"); bool has_url = root.get_object_member("entities").has_member("url"); bool verified = root.get_boolean_member ("verified"); bool protected_user = root.get_boolean_member ("protected"); if (protected_user) { tweet_list.set_placeholder_text (_("Protected profile")); } if (root.has_member ("profile_banner_url")) { string banner_base_url = root.get_string_member ("profile_banner_url"); load_profile_banner (banner_base_url, user_id); } string display_url = ""; Json.Object entities = root.get_object_member ("entities"); if (has_url) { var urls_object = entities.get_object_member("url").get_array_member("urls"). get_element(0).get_object(); var url = urls_object.get_string_member("expanded_url"); if (urls_object.has_member ("display_url")) { display_url = urls_object.get_string_member("expanded_url"); } else { url = urls_object.get_string_member("url"); display_url = url; } } string location = null; if (root.has_member("location")) { location = root.get_string_member("location"); } TextEntity[] text_urls; if (root.has_member ("description")) { Json.Array urls = entities.get_object_member ("description").get_array_member ("urls"); text_urls = new TextEntity[urls.get_length ()]; urls.foreach_element ((arr, i, node) => { var ent = node.get_object (); string expanded_url = ent.get_string_member ("expanded_url"); expanded_url = expanded_url.replace ("&", "&"); Json.Array indices = ent.get_array_member ("indices"); text_urls[i] = TextEntity(){ from = (int)indices.get_int_element (0), to = (int)indices.get_int_element (1), target = expanded_url, display_text = ent.get_string_member ("display_url") }; }); } else text_urls = new TextEntity[0]; account.user_counter.user_seen (id, screen_name, name); set_data(name, screen_name, display_url, location, description, tweets, following, followers, avatar_url, verified, ref text_urls); this.follow_button.following = is_following; this.follow_button.sensitive = (this.user_id != this.account.id); Corebird.db.replace ("profiles") .vali64 ("id", id) .val ("screen_name", screen_name) .val ("name", name) .vali ("followers", followers) .vali ("following", following) .vali ("tweets", tweets) .val ("description", TextTransform.transform (description, text_urls, 0)) .val ("avatar_name", avatar_name) .val ("url", display_url) .val ("location", location) .valb ("is_following", is_following) .run (); } //}}} private async void load_tweets () { // {{{ tweet_list.set_unempty (); tweets_loading = true; int requested_tweet_count = 10; var call = account.proxy.new_call (); call.set_function ("1.1/statuses/user_timeline.json"); call.set_method ("GET"); call.add_param ("user_id", this.user_id.to_string ()); call.add_param ("count", requested_tweet_count.to_string ()); call.add_param ("contributor_details", "true"); call.add_param ("include_my_retweet", "true"); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); tweet_list.set_empty (); return; } var root_array = root.get_array (); if (root_array.get_length () == 0) { tweet_list.set_empty (); return; } yield TweetUtils.work_array (root_array, tweet_list, main_window, account); tweets_loading = false; } // }}} private async void load_older_tweets () { // {{{ if (tweets_loading) return; if (user_stack.visible_child != tweet_list) return; tweets_loading = true; int requested_tweet_count = 15; var call = account.proxy.new_call (); call.set_function ("1.1/statuses/user_timeline.json"); call.set_method ("GET"); call.add_param ("user_id", this.user_id.to_string ()); call.add_param ("count", requested_tweet_count.to_string ()); call.add_param ("contributor_details", "true"); call.add_param ("include_my_retweet", "true"); call.add_param ("max_id", (tweet_list.model.lowest_id - 1).to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return; } var root_arr = root.get_array (); yield TweetUtils.work_array (root_arr, tweet_list, main_window, account); tweets_loading = false; } // }}} private async void load_followers () { if (this.followers_cursor != null && this.followers_cursor.full) return; if (this.followers_loading) return; this.followers_loading = true; this.followers_cursor = yield UserUtils.load_followers (this.account, this.user_id, this.followers_cursor); var users_array = this.followers_cursor.json_object.get_array (); users_array.foreach_element ((array, index, node) => { var user_obj = node.get_object (); var entry = new UserListEntry (); entry.show_settings = false; entry.user_id = user_obj.get_int_member ("id"); entry.screen_name = user_obj.get_string_member ("screen_name"); entry.name = user_obj.get_string_member ("name"); entry.avatar = user_obj.get_string_member ("profile_image_url"); entry.get_style_context ().add_class ("tweet"); entry.show (); this.followers_list.add (entry); }); this.followers_loading = false; } private async void load_following () { if (this.following_cursor != null && this.following_cursor.full) return; if (this.following_loading) return; this.following_loading = true; this.following_cursor = yield UserUtils.load_following (this.account, this.user_id, this.following_cursor); var users_array = this.following_cursor.json_object.get_array (); users_array.foreach_element ((array, index, node) => { var user_obj = node.get_object (); var entry = new UserListEntry (); entry.show_settings = false; entry.user_id = user_obj.get_int_member ("id"); entry.screen_name = user_obj.get_string_member ("screen_name"); entry.name = user_obj.get_string_member ("name"); entry.avatar = user_obj.get_string_member ("profile_image_url"); entry.get_style_context ().add_class ("tweet"); entry.show (); this.following_list.add (entry); }); this.following_loading = false; } /** * Loads the user's banner image. * * @param base_url The "base url" of the banner, obtained from the users/show call from Twitter. * @param user_id Foo * @param screen_name Bar */ private void load_profile_banner (string base_url, int64 user_id) { // {{{ string banner_name = Utils.get_banner_name (user_id); string saved_banner_url = Dirs.cache ("assets/banners/" + banner_name); string banner_url = base_url + "/mobile_retina"; string banner_on_disk = Dirs.cache("assets/banners/" + banner_name); if (!FileUtils.test (banner_on_disk, FileTest.EXISTS) || banner_url != saved_banner_url) { Utils.download_file_async.begin (banner_url, banner_on_disk, data_cancellable, () => {load_banner (banner_on_disk);}); Corebird.db.update ("profiles") .val ("banner_url", banner_url) .where_eqi ("id", user_id) .run (); } else { load_banner (banner_on_disk); } } // }}} private new void set_data (string name, string screen_name, string? url, string? location, string description, int tweets, int following, int followers, string avatar_url, bool verified, ref TextEntity[]? text_urls ) { //{{{ var section = (GLib.Menu)more_menu.get_item_link (0, GLib.Menu.LINK_SECTION); var user_item = new GLib.MenuItem (_("Tweet to @%s").printf (screen_name), "user.tweet-to"); section.remove (1); section.insert_item (1, user_item); name_label.set_markup("%s".printf (name.strip ())); screen_name_label.set_label ("@" + screen_name); //tweet_to_menu_item.label = _("Tweet to @%s").printf (screen_name); string desc = description; if (text_urls != null) { TweetUtils.sort_entities (ref text_urls); desc = TextTransform.transform (description, text_urls, 0); } this.follower_count = followers; description_label.label = "" + desc + ""; tweets_label.label = "%'d".printf(tweets); following_label.label = "%'d".printf(following); update_follower_label (); if (location != null && location != "") { location_label.visible = true; location_label.label = location; } else location_label.visible = false; avatar_image.verified = verified; if (url != null && url != "") { url_label.visible = true; url_label.set_markup ("%s".printf (url, url)); description_label.margin_bottom = 6; } else { url_label.visible = false; description_label.margin_bottom = 12; } this.name = name; this.screen_name = screen_name; this.avatar_url = avatar_url; } //}}} [GtkCallback] private void follow_button_clicked_cb () { //{{{ var call = account.proxy.new_call(); HomeTimeline ht = (HomeTimeline) main_window.get_page (Page.STREAM); if (follow_button.following) { call.set_function( "1.1/friendships/destroy.json"); ht.hide_tweets_from (this.user_id, Tweet.HIDDEN_UNFOLLOWED); ht.hide_retweets_from (this.user_id, Tweet.HIDDEN_UNFOLLOWED); follower_count --; account.unfollow_id (this.user_id); ((SimpleAction)actions.lookup_action ("toggle-retweets")).set_enabled (false); set_retweets_disabled (false); } else { call.set_function ("1.1/friendships/create.json"); call.add_param ("follow", "false"); ht.show_tweets_from (this.user_id, Tweet.HIDDEN_UNFOLLOWED); if (!((SimpleAction)actions.lookup_action ("toggle-retweets")).get_state ().get_boolean ()) { ht.show_retweets_from (this.user_id, Tweet.HIDDEN_UNFOLLOWED); } set_user_blocked (false); follower_count ++; account.follow_id (this.user_id); ((SimpleAction)actions.lookup_action ("toggle-retweets")).set_enabled (true); } update_follower_label (); progress_spinner.start (); loading_stack.visible_child_name = "progress"; follow_button.sensitive = false; call.set_method ("POST"); call.add_param ("id", user_id.to_string ()); call.invoke_async.begin (null, (obj, res) => { try { this.follow_button.following = !this.follow_button.following; this.follow_button.sensitive = (this.user_id != this.account.id); call.invoke_async.end (res); } catch (GLib.Error e) { critical (e.message); critical (call.get_payload ()); } follow_button.sensitive = true; progress_spinner.stop (); loading_stack.visible_child_name = "data"; }); } //}}} [GtkCallback] private bool activate_link (string uri) { return TweetUtils.activate_link (uri, main_window); } private void load_banner (string? path) { try { if (path != null) banner_image.pixbuf = new Gdk.Pixbuf.from_file (path); else banner_image.pixbuf = new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/no_banner.png"); } catch (GLib.Error e) { warning (e.message); } } /** * see IPage#onJoin */ public void on_join (int page_id, Bundle? args) { int64 user_id = args.get_int64 ("user_id"); if (user_id == -1) return; string? screen_name = args.get_string ("screen_name"); if (screen_name != null) { this.screen_name = screen_name; } data_cancellable = new GLib.Cancellable (); if (user_id != this.user_id) { reset_data (); followers_cursor = null; followers_list.remove_all (); following_cursor = null; following_list.remove_all (); set_user_id (user_id); this.follow_button.following = account.follows_id (user_id); tweet_list.model.clear (); user_lists.clear_lists (); lists_page_inited = false; load_tweets.begin (); } tweet_list.reset_placeholder_text (); followers_list.reset_placeholder_text (); following_list.reset_placeholder_text (); tweets_button.active = true; //user_stack.visible_child = tweet_list; } public void on_leave () { // We might otherwise overwrite the new user's data with that from the old one. data_cancellable.cancel (); banner_image.scale = 0.3; } private void reset_data () { name_label.label = " "; screen_name_label.label = " "; description_label.label = " "; url_label.label = " "; location_label.label = " "; tweets_label.label = " "; following_label.label = " "; followers_label.label = " "; avatar_image.surface = null; } public void create_tool_button (Gtk.RadioButton? group) {} public string? get_title () { return "@" + screen_name; } public Gtk.RadioButton? get_tool_button(){ return null; } private void write_dm_activated (GLib.SimpleAction a, GLib.Variant? v) { var bundle = new Bundle (); bundle.put_int64 ("sender_id", user_id); bundle.put_string ("screen_name", screen_name); bundle.put_string ("name", name); bundle.put_string ("avatar_url", avatar_url.replace ("_bigger", "_normal")); main_window.main_widget.switch_page (Page.DM, bundle); } private void tweet_to_activated (GLib.SimpleAction a, GLib.Variant? v) { var cw = new ComposeTweetWindow (main_window, account, null); cw.set_text ("@" + screen_name + " "); cw.show_all (); } private void add_remove_list_activated (GLib.SimpleAction a, GLib.Variant? v) { var uld = new UserListDialog (main_window, account, user_id); uld.load_lists (); uld.show_all (); } private void toggle_blocked_activated (GLib.SimpleAction a, GLib.Variant? v) { if (block_item_blocked) return; block_item_blocked = true; bool current_state = get_user_blocked (); HomeTimeline ht = (HomeTimeline) main_window.get_page (Page.STREAM); var call = account.proxy.new_call (); call.set_method ("POST"); if (current_state) { call.set_function ("1.1/blocks/destroy.json"); ht.show_tweets_from (this.user_id, Tweet.HIDDEN_AUTHOR_BLOCKED); } else { call.set_function ("1.1/blocks/create.json"); this.follow_button.following = false; this.follow_button.sensitive = (this.user_id != this.account.id); ht.hide_tweets_from (this.user_id, Tweet.HIDDEN_AUTHOR_BLOCKED); } set_user_blocked (!current_state); call.add_param ("user_id", this.user_id.to_string ()); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); /* Reset the state if the blocking failed */ a.set_state (new GLib.Variant.boolean (current_state)); } block_item_blocked = false; }); } private void retweet_action_activated (GLib.SimpleAction a, GLib.Variant? v) { if (retweet_item_blocked) return; retweet_item_blocked = true; bool current_state = a.get_state ().get_boolean (); a.set_state (new GLib.Variant.boolean (!current_state)); var call = account.proxy.new_call (); call.set_function ("1.1/friendships/update.json"); call.set_method ("POST"); call.add_param ("user_id", this.user_id.to_string ()); call.add_param ("retweets", current_state.to_string ()); HomeTimeline ht = (HomeTimeline) main_window.get_page (Page.STREAM); if (current_state) { ht.show_retweets_from (this.user_id, Tweet.HIDDEN_RTS_DISABLED); account.remove_disabled_rts_id (this.user_id); } else { ht.hide_retweets_from (this.user_id, Tweet.HIDDEN_RTS_DISABLED); account.add_disabled_rts_id (this.user_id); } call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); /* Reset the state if the retweeting failed */ a.set_state (new GLib.Variant.boolean (current_state)); } retweet_item_blocked = false; }); } private void set_user_blocked (bool blocked) { ((SimpleAction)actions.lookup_action ("toggle-blocked")).set_state (new GLib.Variant.boolean (blocked)); } private bool get_user_blocked () { return ((SimpleAction)actions.lookup_action ("toggle-blocked")).get_state ().get_boolean (); } private void set_retweets_disabled (bool disabled) { ((SimpleAction)actions.lookup_action ("toggle-retweets")).set_state (new GLib.Variant.boolean (disabled)); } private void update_follower_label () { followers_label.label = "%'d".printf(follower_count); } public void stream_message_received (StreamMessageType type, Json.Node root_node) { if (type == StreamMessageType.TWEET) { var obj = root_node.get_object (); var user = obj.get_object_member ("user"); if (user.get_int_member ("id") != this.user_id) return; // Correct user! var tweet = new Tweet (); tweet.load_from_json (root_node, new GLib.DateTime.now_local (), this.account); this.tweet_list.model.add (tweet); } } [GtkCallback] private void tweets_button_toggled_cb (GLib.Object source) { if (((Gtk.RadioButton)source).active) { this.balance_next_upper_change (BOTTOM); user_stack.visible_child = tweet_list; } } [GtkCallback] private void followers_button_toggled_cb (GLib.Object source) { if (((Gtk.RadioButton)source).active) { if (this.followers_cursor == null) { this.load_followers.begin (); } this.balance_next_upper_change (BOTTOM); user_stack.visible_child = followers_list; } } [GtkCallback] private void following_button_toggled_cb (GLib.Object source) { if (((Gtk.RadioButton)source).active) { if (this.following_cursor == null) { this.load_following.begin (); } this.balance_next_upper_change (BOTTOM); user_stack.visible_child = following_list; } } [GtkCallback] private void lists_button_toggled_cb (GLib.Object source) { if (((Gtk.RadioButton)source).active) { if (!lists_page_inited) { user_lists.load_lists.begin (user_id); lists_page_inited = true; } this.balance_next_upper_change (BOTTOM); user_stack.visible_child = user_lists; } } } corebird-1.1/src/SearchPage.vala000066400000000000000000000230741260276623600166220ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/search-page.ui")] class SearchPage : IPage, Gtk.Box { private static const int USER_COUNT = 3; /** The unread count here is always zero */ public int unread_count { get { return 0; } set {;} } public unowned Account account { get; set; } public unowned MainWindow main_window { set; get; } public int id { get; set; } [GtkChild] private Gtk.SearchEntry search_entry; [GtkChild] private Gtk.Button search_button; [GtkChild] private TweetListBox tweet_list; [GtkChild] private Gtk.Label users_header; [GtkChild] private Gtk.Label tweets_header; [GtkChild] private ScrollWidget scroll_widget; private Gtk.RadioButton tool_button; public DeltaUpdater delta_updater; private LoadMoreEntry load_more_entry = new LoadMoreEntry (); private string search_query; private int user_page = 1; private int64 lowest_tweet_id = int64.MAX-1; private bool loading_tweets = false; private Gtk.Widget last_focus_widget; private int n_results = 0; private Collect collect_obj; private uint remove_content_timeout = 0; public SearchPage (int id, Account account) { this.id = id; this.account = account; /* We are slightly abusing the TweetListBox here */ tweet_list.bind_model (null, null); tweet_list.set_header_func (header_func); tweet_list.set_sort_func (ITwitterItem.sort_func); tweet_list.row_activated.connect (row_activated_cb); search_button.clicked.connect (() => { search_for (search_entry.get_text()); }); load_more_entry.get_button ().clicked.connect (() => { user_page++; load_users (); }); scroll_widget.scrolled_to_end.connect (load_tweets); tweet_list.get_placeholder ().hide (); tweet_list.set_adjustment (scroll_widget.get_vadjustment ()); } [GtkCallback] private void search_entry_activate_cb () { search_for (search_entry.get_text ()); } /** * see IPage#onJoin */ public void on_join (int page_id, Bundle? args) { string? term = args != null ? args.get_string ("query") : null; if (this.remove_content_timeout != 0) { GLib.Source.remove (this.remove_content_timeout); this.remove_content_timeout = 0; } if (term == null) { if (last_focus_widget != null) last_focus_widget.grab_focus (); else search_entry.grab_focus (); return; } search_for (term, true); } public void on_leave () { this.remove_content_timeout = GLib.Timeout.add (3 * 1000 * 60, () => { foreach (Gtk.Widget w in tweet_list.get_children ()) { // We are still using raw widgets here. tweet_list.remove (w); } tweet_list.get_placeholder ().hide (); this.remove_content_timeout = 0; return GLib.Source.REMOVE; }); } public void search_for (string search_term, bool set_text = false) { //{{{ if(search_term.length == 0) return; n_results = 0; string q = search_term; // clear the list tweet_list.remove_all (); tweet_list.set_unempty (); tweet_list.get_placeholder ().show (); if (set_text) search_entry.set_text(search_term); q += " -rt"; this.search_query = GLib.Uri.escape_string (q); this.user_page = 1; this.lowest_tweet_id = int64.MAX-1; collect_obj = new Collect (2); collect_obj.finished.connect (show_entries); load_tweets (); load_users (); } //}}} private void row_activated_cb (Gtk.ListBoxRow row) { // {{{ this.last_focus_widget = row; var bundle = new Bundle (); if (row is UserListEntry) { bundle.put_int64 ("user_id", ((UserListEntry)row).user_id); bundle.put_string ("screen_name", ((UserListEntry)row).screen_name); main_window.main_widget.switch_page (Page.PROFILE, bundle); } else if (row is TweetListEntry) { bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); } } //}}} private void header_func (Gtk.ListBoxRow row, Gtk.ListBoxRow? before) { //{{{ Gtk.Widget header = row.get_header (); if (header != null) return; if (before == null && row is UserListEntry) { row.set_header (users_header); } else if ((before is UserListEntry || before is LoadMoreEntry) && row is TweetListEntry) { row.set_header (tweets_header); } } //}}} private void load_users () { // {{{ var user_call = account.proxy.new_call (); user_call.set_method ("GET"); user_call.set_function ("1.1/users/search.json"); user_call.add_param ("q", this.search_query); user_call.add_param ("count", (USER_COUNT + 1).to_string ()); user_call.add_param ("include_entities", "false"); user_call.add_param ("page", user_page.to_string ()); TweetUtils.load_threaded.begin (user_call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); if (!collect_obj.done) collect_obj.emit (); return; } var users = root.get_array (); if (users.get_length () == 0 && n_results <= 0) n_results = -1; else n_results += (int)users.get_length (); if (n_results <= 0) { tweet_list.set_empty (); } users.foreach_element ((array, index, node) => { if (index > USER_COUNT - 1) return; var user_obj = node.get_object (); var entry = new UserListEntry (); entry.screen_name = "@" + user_obj.get_string_member ("screen_name"); entry.name = user_obj.get_string_member ("name").strip (); entry.avatar = user_obj.get_string_member ("profile_image_url"); entry.user_id = user_obj.get_int_member ("id"); entry.show_settings = false; if (!collect_obj.done) entry.visible = false; tweet_list.add (entry); }); if (users.get_length () > USER_COUNT) { if (load_more_entry.parent == null) { load_more_entry.visible = false; tweet_list.add (load_more_entry); } } else { load_more_entry.hide (); } if (!collect_obj.done) collect_obj.emit (); }); } // }}} private void load_tweets () { // {{{ if (loading_tweets) return; loading_tweets = true; var call = account.proxy.new_call (); call.set_function ("1.1/search/tweets.json"); call.set_method ("GET"); call.add_param ("q", this.search_query); call.add_param ("max_id", (lowest_tweet_id - 1).to_string ()); call.add_param ("count", "35"); TweetUtils.load_threaded.begin (call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); if (!collect_obj.done) collect_obj.emit (); return; } var now = new GLib.DateTime.now_local (); var statuses = root.get_object().get_array_member("statuses"); if (statuses.get_length () == 0 && n_results <= 0) n_results = -1; else n_results += (int)statuses.get_length (); if (n_results <= 0) tweet_list.set_empty (); statuses.foreach_element ((array, index, node) => { var tweet = new Tweet (); tweet.load_from_json (node, now, account); if (tweet.id < lowest_tweet_id) lowest_tweet_id = tweet.id; var entry = new TweetListEntry (tweet, main_window, account); delta_updater.add (entry); if (!collect_obj.done) entry.visible = false; else entry.show (); tweet_list.add (entry); }); loading_tweets = false; if (!collect_obj.done) collect_obj.emit (); }); } // }}} private void show_entries (GLib.Error? e) { if (e != null) { tweet_list.set_error (e.message); tweet_list.set_empty (); return; } tweet_list.@foreach ((w) => w.show()); } public void create_tool_button (Gtk.RadioButton? group){ tool_button = new BadgeRadioToolButton (group, "edit-find-symbolic", _("Search")); } public Gtk.RadioButton? get_tool_button() { return tool_button; } public string? get_title () { return _("Search"); } public bool handles_double_open () { return true; } } [GtkTemplate (ui = "/org/baedert/corebird/ui/load-more-entry.ui")] class LoadMoreEntry : Gtk.ListBoxRow, ITwitterItem { public int64 sort_factor { get { return int64.MAX-2; } } public bool seen { get { return true; } set {} } [GtkChild] private Gtk.Button load_more_button; public LoadMoreEntry () { this.activatable = false; } public Gtk.Button get_button () { return load_more_button; } public int update_time_delta (GLib.DateTime? now = null) {return 0;} } corebird-1.1/src/Settings.vala000066400000000000000000000056001260276623600164130ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Settings : GLib.Object { private static GLib.Settings settings; public static void init(){ settings = new GLib.Settings("org.baedert.corebird"); } public static new GLib.Settings get () { return settings; } /** * Returns how many tweets should be stacked before a * notification should be created. */ public static int get_tweet_stack_count() { int setting_val = settings.get_enum("new-tweets-notify"); return setting_val; } /** * Check whether the user wants Corebird to always use the dark gtk theme variant. */ public static bool use_dark_theme(){ return settings.get_boolean("use-dark-theme"); } public static bool notify_new_mentions(){ return settings.get_boolean("new-mentions-notify"); } public static bool notify_new_dms(){ return settings.get_boolean("new-dms-notify"); } public static bool show_inline_media(){ return settings.get_boolean("show-inline-media"); } public static bool auto_scroll_on_new_tweets () { return settings.get_boolean ("auto-scroll-on-new-tweets"); } public static string get_accel (string accel_name) { return settings.get_string ("accel-" + accel_name); } public static double max_media_size () { return settings.get_double ("max-media-size"); } public static void toggle_sidebar_visible () { settings.set_boolean ("sidebar-visible", !settings.get_boolean ("sidebar-visible")); } public static string get_consumer_key () { return settings.get_string ("consumer-key"); } public static string get_consumer_secret () { return settings.get_string ("consumer-secret"); } public static void add_text_transform_flag (TransformFlags flag) { settings.set_uint ("text-transform-flags", settings.get_uint ("text-transform-flags") | flag); } public static void remove_text_transform_flag (TransformFlags flag) { settings.set_uint ("text-transform-flags", settings.get_uint ("text-transform-flags") & ~flag); } public static TransformFlags get_text_transform_flags () { return (TransformFlags) settings.get_uint ("text-transform-flags"); } } corebird-1.1/src/SnippetManager.vala000066400000000000000000000054051260276623600175330ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class SnippetManager : GLib.Object { private Gee.HashMap snippets = new Gee.HashMap (); private bool inited = false; public delegate void SnippetQueryFunc (string key, string value); public SnippetManager () { } private void load_snippets () { Corebird.db.select ("snippets") .cols ("id", "key", "value") .order ("id") .run ((vals) => { snippets.set (vals[1], vals[2]); return true; }); inited = true; } public void remove_snippet (string snippet_key) { if (!inited) load_snippets (); this.snippets.unset (snippet_key); Corebird.db.exec (@"DELETE FROM `snippets` WHERE `key`='$(snippet_key)'"); } public void insert_snippet (string key, string value) { if (!inited) load_snippets (); if (this.snippets.has_key (key)) error ("Snippet already exists: %s", key); // Insert snippet into db Corebird.db.insert ("snippets") .val ("key", key) .val ("value", value) .run (); this.snippets.set (key, value); } public string? get_snippet (string key) { if (!inited) load_snippets (); return this.snippets.get (key); } public void query_snippets (SnippetQueryFunc func) { if (!inited) load_snippets (); foreach (var entry in this.snippets.entries) { func (entry.key, entry.value); } } public int n_snippets () { if (!inited) load_snippets (); return this.snippets.size; } public void set_snippet (string old_key, string key, string new_value) { if (!inited) load_snippets (); if (!this.snippets.has_key (old_key)) { debug ("Key %s not in hashmap!", key); return; } // Delete the old one, add the new one, update the db this.snippets.unset (key); this.snippets.set (key, new_value); Corebird.db.update ("snippets") .val ("key", key) .val ("value", new_value) .where_eq ("key", old_key) .run (); } } corebird-1.1/src/Tweet.vala000066400000000000000000000364151260276623600157130ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public struct UserIdentity { int64 id; string screen_name; string user_name; } UserIdentity? parse_identity (Json.Object user_obj) { UserIdentity id = {}; id.id = user_obj.get_int_member ("id"); id.screen_name = user_obj.get_string_member ("screen_name"); id.user_name = user_obj.get_string_member ("name").replace ("&", "&").strip (); return id; } // XXX FUCK THIS SHOULD BE A STRUCT FFS public class MiniTweet { public int64 id; public int64 created_at; public UserIdentity author; public string text; public TextEntity[] entities; public Media[] medias; } MiniTweet? parse_mini_tweet (Json.Object status) { MiniTweet mt = new MiniTweet (); mt.id = status.get_int_member ("id"); mt.author = parse_identity (status.get_object_member ("user")); mt.text = status.get_string_member ("text"); mt.created_at = Utils.parse_date (status.get_string_member ("created_at")).to_unix (); return mt; } void parse_entities (MiniTweet mt, Json.Object status) { // {{{ var entities = status.get_object_member ("entities"); var urls = entities.get_array_member("urls"); var hashtags = entities.get_array_member ("hashtags"); var user_mentions = entities.get_array_member ("user_mentions"); int media_count = Utils.get_json_array_size (entities, "media"); if (status.has_member ("extended_entities")) media_count += Utils.get_json_array_size (status.get_object_member ("extended_entities"), "media"); media_count += (int)urls.get_length (); mt.medias = new Media[media_count]; int real_media_count = 0; /* Overallocate here, remove the unnecessary parts later. */ mt.entities = new TextEntity[urls.get_length () + hashtags.get_length () + user_mentions.get_length () + media_count]; int url_index = 0; urls.foreach_element((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member("expanded_url"); if (is_media_candidate (expanded_url)) { var m = new Media (); m.url = expanded_url; m.id = real_media_count; m.type = Media.type_from_url (expanded_url); mt.medias[real_media_count] = m; real_media_count ++; } Json.Array indices = url.get_array_member ("indices"); expanded_url = expanded_url.replace("&", "&"); mt.entities[url_index] = TextEntity () { from = (uint) indices.get_int_element (0), to = (uint) indices.get_int_element (1), display_text = url.get_string_member ("display_url"), tooltip_text = expanded_url, target = expanded_url }; url_index ++; }); hashtags.foreach_element ((arr, index, node) => { var hashtag = node.get_object (); Json.Array indices = hashtag.get_array_member ("indices"); mt.entities[url_index] = TextEntity () { from = (uint) indices.get_int_element (0), to = (uint) indices.get_int_element (1), display_text = "#" + hashtag.get_string_member ("text"), tooltip_text = "#" + hashtag.get_string_member ("text"), target = null // == display_text }; url_index ++; }); user_mentions.foreach_element ((arr, index, node) => { var mention = node.get_object (); Json.Array indices = mention.get_array_member ("indices"); string screen_name = mention.get_string_member ("screen_name"); mt.entities[url_index] = TextEntity () { from = (uint) indices.get_int_element (0), to = (uint) indices.get_int_element (1), display_text = "@" + screen_name, target = "@" + mention.get_string_member ("id_str") + "/@" + screen_name, tooltip_text = mention.get_string_member ("name") }; url_index ++; }); // The same with media if (entities.has_member ("media")) { var medias = entities.get_array_member ("media"); medias.foreach_element ((arr, index, node) => { var url = node.get_object(); string expanded_url = url.get_string_member ("expanded_url"); expanded_url = expanded_url.replace ("&", "&"); Json.Array indices = url.get_array_member ("indices"); mt.entities[url_index] = TextEntity () { from = (uint) indices.get_int_element (0), to = (uint) indices.get_int_element (1), target = url.get_string_member ("url"), display_text = url.get_string_member ("display_url") }; url_index ++; string media_url = url.get_string_member ("media_url"); if (is_media_candidate (media_url)) { var m = new Media (); m.url = media_url; m.target_url = media_url + ":large"; mt.medias[real_media_count] = m; real_media_count ++; } }); } if (status.has_member ("extended_entities")) { var extended_entities = status.get_object_member ("extended_entities"); var extended_media = extended_entities.get_array_member ("media"); extended_media.foreach_element ((arr, index, node) => { var media_obj = node.get_object (); string media_type = media_obj.get_string_member ("type"); if (media_type == "photo") { string url = media_obj.get_string_member ("media_url"); foreach (Media m in mt.medias) { if (m != null && m.url == url) return; } if (is_media_candidate (url)) { var m = new Media (); m.url = url; m.target_url = url + ":large"; m.id = media_obj.get_int_member ("id"); m.type = Media.type_from_string (media_obj.get_string_member ("type")); mt.medias[real_media_count] = m; real_media_count ++; } } else if (media_type == "video" || media_type == "animated_gif") { Json.Object? variant = null; Json.Array variants = media_obj.get_object_member ("video_info") .get_array_member ("variants"); /* Just pick the first mp4 variant */ for (uint i = 0; i < variants.get_length (); i ++) { variant = variants.get_element (i).get_object (); if (variant.get_string_member ("content_type") == "video/mp4") break; } if (variant != null) { Media m = new Media (); m.url = variant.get_string_member ("url"); m.thumb_url = media_obj.get_string_member ("media_url"); m.type = MediaType.TWITTER_VIDEO; m.id = media_obj.get_int_member ("id"); mt.medias[real_media_count] = m; real_media_count ++; } } }); } mt.medias.resize (real_media_count); InlineMediaDownloader.get ().load_all_media (mt, mt.medias); /* Remove unnecessary url entries */ mt.entities.resize (url_index); TweetUtils.sort_entities (ref mt.entities); } // }}} public class Tweet : GLib.Object { public static const int MAX_LENGTH = 140; /** Force hiding (there's no way this flag will ever get flipped...)*/ public const uint HIDDEN_FORCE = 1 << 0; /** Hidden because we unfolled the author */ public const uint HIDDEN_UNFOLLOWED = 1 << 1; /** Hidden because one of the filters matched the tweet */ public const uint HIDDEN_FILTERED = 1 << 2; /** Hidden because RTs of the author are disabled */ public const uint HIDDEN_RTS_DISABLED = 1 << 3; /** Hidden because it's a RT by the authenticating user */ public const uint HIDDEN_RT_BY_USER = 1 << 4; public const uint HIDDEN_RT_BY_FOLLOWEE = 1 << 5; /** Hidden because the author is blocked */ public const uint HIDDEN_AUTHOR_BLOCKED = 1 << 6; /** Hidden because the author of a retweet is blocked */ public const uint HIDDEN_RETWEETER_BLOCKED = 1 << 7; public uint hidden_flags = 0; #if DEBUG public string json_data; #endif public bool is_hidden { get { return hidden_flags > 0; } } public signal void hidden_flags_changed (); public int64 id; public bool retweeted { get; set; default = false; } public bool favorited { get; set; default = false; } public bool deleted { get; set; default = false; } public int64 user_id { get { if (this.retweeted_tweet != null) return this.retweeted_tweet.author.id; else return this.source_tweet.author.id; } } public string screen_name { get { if (this.retweeted_tweet != null) return this.retweeted_tweet.author.screen_name; else return this.source_tweet.author.screen_name; } } public string user_name { get { if (this.retweeted_tweet != null) return this.retweeted_tweet.author.user_name; else return this.source_tweet.author.user_name; } } public MiniTweet source_tweet; public MiniTweet? retweeted_tweet = null; public MiniTweet? quoted_tweet = null; public Cairo.Surface avatar { get; set; } /** The avatar url on the server */ public string avatar_url; public bool verified = false; public int64 my_retweet; public bool protected; public string? notification_id = null; private bool _seen = true; public bool seen { get { return _seen; } set { _seen = value; if (value && notification_id != null) { NotificationManager.withdraw (this.notification_id); this.notification_id = null; } } } /** if 0, this tweet is NOT part of a conversation */ public int64 reply_id = 0; public Media[] medias { get { if (this.retweeted_tweet != null) return this.retweeted_tweet.medias; else if (this.quoted_tweet != null) return this.quoted_tweet.medias; else return this.source_tweet.medias; } } public bool has_inline_media { get { if (this.retweeted_tweet != null) return retweeted_tweet.medias != null && retweeted_tweet.medias.length > 0; else if (this.quoted_tweet != null) return quoted_tweet.medias != null && quoted_tweet.medias.length > 0; else return source_tweet.medias != null && source_tweet.medias.length > 0; } } public int retweet_count; public int favorite_count; public Tweet () { this.avatar = Twitter.no_avatar; } public string[] get_mentions () { TextEntity[] entities; if (this.retweeted_tweet != null) entities = this.retweeted_tweet.entities; else entities = this.source_tweet.entities; string[] e = new string[entities.length]; int n_mentions = 0; foreach (var entity in entities) { if (entity.display_text[0] == '@') { e[n_mentions] = entity.display_text; n_mentions ++; } } e.resize (n_mentions); return e; } /** * Fills all the data of this tweet from Json data. * @param status The Json object to get the data from * @param now The current time */ public void load_from_json (Json.Node status_node, GLib.DateTime now, Account account) { Json.Object status = status_node.get_object (); Json.Object user = status.get_object_member("user"); this.id = status.get_int_member("id"); this.favorited = status.get_boolean_member("favorited"); this.retweeted = status.get_boolean_member("retweeted"); this.retweet_count = (int)status.get_int_member ("retweet_count"); this.favorite_count = (int)status.get_int_member ("favorite_count"); this.source_tweet = parse_mini_tweet (status); if (status.has_member("retweeted_status")) { Json.Object rt = status.get_object_member("retweeted_status"); this.retweeted_tweet = parse_mini_tweet (rt); parse_entities (this.retweeted_tweet, rt); Json.Object rt_user = rt.get_object_member("user"); this.avatar_url = rt_user.get_string_member ("profile_image_url"); this.verified = rt_user.get_boolean_member ("verified"); this.protected = rt_user.get_boolean_member ("protected"); if (!rt.get_null_member ("in_reply_to_status_id")) this.reply_id = rt.get_int_member ("in_reply_to_status_id"); } else { parse_entities (this.source_tweet, status); this.avatar_url = user.get_string_member ("profile_image_url"); this.verified = user.get_boolean_member ("verified"); this.protected = user.get_boolean_member ("protected"); if (!status.get_null_member ("in_reply_to_status_id")) this.reply_id = status.get_int_member ("in_reply_to_status_id"); } if (status.has_member ("quoted_status")) { var quoted_status = status.get_object_member ("quoted_status"); this.quoted_tweet = parse_mini_tweet (quoted_status); parse_entities (this.quoted_tweet, quoted_status); } else if (this.retweeted_tweet != null && status.get_object_member ("retweeted_status").has_member ("quoted_status")) { var quoted_status = status.get_object_member ("retweeted_status").get_object_member ("quoted_status"); this.quoted_tweet = parse_mini_tweet (quoted_status); parse_entities (this.quoted_tweet, quoted_status); } if (status.has_member ("current_user_retweet")) { this.my_retweet = status.get_object_member ("current_user_retweet").get_int_member ("id"); this.retweeted = true; } this.avatar = Twitter.get ().get_avatar (avatar_url, (a) => { this.avatar = a; }); #if DEBUG var gen = new Json.Generator (); gen.root = status_node; gen.pretty = true; this.json_data = gen.to_data (null); #endif } /** * Returns the text of this tweet in pango markup form, * i.e. formatted with the html tags used by pango. * * @return The tweet's formatted text. */ public string get_formatted_text () { MiniTweet t; if (this.retweeted_tweet != null) t = this.retweeted_tweet; else t = this.source_tweet; return TextTransform.transform_tweet (t, 0); } /** * Returns the text of this tweet, with its long urls. * Twitter automatically shortens them. * * @return The tweet's text with long urls */ public string get_real_text () { MiniTweet t; if (this.retweeted_tweet != null) t = this.retweeted_tweet; else t = this.source_tweet; return TextTransform.transform_tweet (t, TransformFlags.EXPAND_LINKS); } public string get_trimmed_text () { MiniTweet t; if (this.retweeted_tweet != null) t = this.retweeted_tweet; else t = this.source_tweet; int64 quote_id = this.quoted_tweet != null ? this.quoted_tweet.id : -1; return TextTransform.transform_tweet (t, Settings.get_text_transform_flags (), quote_id); } } corebird-1.1/src/TweetInfoPage.vala000066400000000000000000000376441260276623600173310ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/tweet-info-page.ui")] class TweetInfoPage : IPage, ScrollWidget, IMessageReceiver { public static const int BY_INSTANCE = 1; public static const int BY_ID = 2; private const GLib.ActionEntry[] action_entries = { {"quote", quote_activated}, }; public int unread_count { get {return 0;} } public int id { get; set; } public unowned MainWindow main_window { get; set; } public unowned Account account { get; set; } public unowned DeltaUpdater delta_updater { set { top_list_box.delta_updater = value; bottom_list_box.delta_updater = value; } } private int64 tweet_id; private string screen_name; private bool values_set = false; private Tweet tweet; private GLib.SimpleActionGroup actions; [GtkChild] private Gtk.Grid grid; [GtkChild] private MultiMediaWidget mm_widget; [GtkChild] private Gtk.Label text_label; [GtkChild] private TextButton name_button; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label rt_label; [GtkChild] private Gtk.Label fav_label; [GtkChild] private TweetListBox bottom_list_box; [GtkChild] private TweetListBox top_list_box; [GtkChild] private Gtk.ToggleButton favorite_button; [GtkChild] private Gtk.ToggleButton retweet_button; [GtkChild] private Gtk.Label time_label; [GtkChild] private Gtk.Label source_label; [GtkChild] private MaxSizeContainer max_size_container; [GtkChild] private ReplyIndicator reply_indicator; [GtkChild] private Gtk.Stack main_stack; [GtkChild] private Gtk.Label error_label; public TweetInfoPage (int id, Account account) { this.id = id; this.account = account; this.top_list_box.account = account; this.bottom_list_box.account = account; mm_widget.media_clicked.connect ((m, i) => TweetUtils.handle_media_click (tweet, main_window, i)); this.scroll_event.connect ((evt) => { if (evt.delta_y < 0 && this.vadjustment.value == 0 && reply_indicator.replies_available) { int inc = (int)(vadjustment.step_increment * (-evt.delta_y)); max_size_container.max_size += inc; return true; } return false; }); bottom_list_box.row_activated.connect ((row) => { var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); bundle.put_bool ("existing", true); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); }); top_list_box.row_activated.connect ((row) => { var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_INSTANCE); bundle.put_object ("tweet", ((TweetListEntry)row).tweet); bundle.put_bool ("existing", true); main_window.main_widget.switch_page (Page.TWEET_INFO, bundle); }); this.actions = new GLib.SimpleActionGroup (); this.actions.add_action_entries (action_entries, this); this.insert_action_group ("tweet", this.actions); } public void on_join (int page_id, Bundle? args) { int mode = args.get_int ("mode"); if (mode == 0) return; values_set = false; bool existing = args.get_bool ("existing", false); reply_indicator.replies_available = false; max_size_container.max_size = 0; main_stack.visible_child = grid; if (existing) { // Only possible BY_INSTANCE Tweet tweet = (Tweet) args.get_object ("tweet"); rearrange_tweets (tweet.id); } else { bottom_list_box.model.clear (); bottom_list_box.hide (); top_list_box.model.clear (); top_list_box.hide (); } if (mode == BY_INSTANCE) { Tweet tweet = (Tweet)args.get_object ("tweet"); if (tweet.retweeted_tweet != null) this.tweet_id = tweet.retweeted_tweet.id; else this.tweet_id = tweet.id; this.screen_name = tweet.screen_name; this.tweet = tweet; set_tweet_data (tweet); } else if (mode == BY_ID) { this.tweet_id = args.get_int64 ("tweet_id"); this.screen_name = args.get_string ("screen_name"); } query_tweet_info (existing); } private void rearrange_tweets (int64 new_id) { //assert (new_id != this.tweet_id); if (top_list_box.model.contains_id (new_id)) { // Move the current tweet down into bottom_list_box bottom_list_box.model.add (this.tweet); bottom_list_box.show (); top_list_box.model.clear (); top_list_box.hide (); } else if (bottom_list_box.model.contains_id (new_id)) { // Remove all tweets above the new one from the bottom list box, // add the direct successor to the top_list top_list_box.model.clear (); top_list_box.show (); var t = bottom_list_box.model.get_from_id (new_id, -1); if (t != null) { top_list_box.model.add (t); } else { top_list_box.model.add (this.tweet); } reply_indicator.replies_available = true; bottom_list_box.model.remove_tweets_above (new_id); if (bottom_list_box.model.get_n_items () == 0) bottom_list_box.hide (); } //else //error ("wtf"); } public void on_leave () {} [GtkCallback] private void favorite_button_toggled_cb () { if (!values_set) return; favorite_button.sensitive = false; if (favorite_button.active) this.tweet.favorite_count ++; else this.tweet.favorite_count --; this.update_rt_fav_labels (); TweetUtils.toggle_favorite_tweet.begin (account, tweet, !favorite_button.active, () => { favorite_button.sensitive = true; }); } [GtkCallback] private void retweet_button_toggled_cb () { if (!values_set) return; retweet_button.sensitive = false; if (retweet_button.active) this.tweet.retweet_count ++; else this.tweet.retweet_count --; this.update_rt_fav_labels (); TweetUtils.toggle_retweet_tweet.begin (account, tweet, !retweet_button.active, () => { retweet_button.sensitive = true; }); } [GtkCallback] private void reply_button_clicked_cb () { ComposeTweetWindow ctw = new ComposeTweetWindow(main_window, this.account, this.tweet, ComposeTweetWindow.Mode.REPLY); ctw.show (); } [GtkCallback] private bool link_activated_cb (string uri) { return TweetUtils.activate_link (uri, main_window); } [GtkCallback] private void name_button_clicked_cb () { int64 id; string screen_name; if (this.tweet.retweeted_tweet != null) { id = this.tweet.retweeted_tweet.author.id; screen_name = this.tweet.retweeted_tweet.author.screen_name; } else { id = this.tweet.source_tweet.author.id; screen_name = this.tweet.source_tweet.author.screen_name; } var bundle = new Bundle (); bundle.put_int64 ("user_id", id); bundle.put_string ("screen_name", screen_name); main_window.main_widget.switch_page (Page.PROFILE, bundle); } /** * Loads the data of the tweet with the id tweet_id from the Twitter server. */ private void query_tweet_info (bool existing) { //{{{ var now = new GLib.DateTime.now_local (); var call = account.proxy.new_call (); call.set_method ("GET"); call.set_function ("1.1/statuses/show.json"); call.add_param ("id", tweet_id.to_string ()); call.add_param ("include_my_retweet", "true"); TweetUtils.load_threaded.begin (call, (__, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { error_label.label = "%s: %s".printf (_("Could not show tweet"), e.message); main_stack.visible_child = error_label; return; } this.tweet = new Tweet (); tweet.load_from_json (root, now, account); Json.Object root_object = root.get_object (); string with = root_object.get_string_member ("source"); with = "" + extract_source (with) + ""; set_tweet_data (tweet, with); if (!existing) load_replied_to_tweet (tweet.reply_id); values_set = true; }); var reply_call = account.proxy.new_call (); reply_call.set_method ("GET"); reply_call.set_function ("1.1/search/tweets.json"); reply_call.add_param ("q", "to:" + this.screen_name); reply_call.add_param ("since_id", tweet_id.to_string ()); reply_call.add_param ("count", "200"); TweetUtils.load_threaded.begin (reply_call, (_, res) => { Json.Node? root = null; try { root = TweetUtils.load_threaded.end (res); } catch (GLib.Error e) { warning (e.message); return; } var statuses_node = root.get_object ().get_array_member ("statuses"); int64 previous_tweet_id = -1; if (top_list_box.model.get_n_items () > 0) { //assert (top_list_box.model.get_n_items () == 1); previous_tweet_id = ((Tweet)(top_list_box.model.get_item (0))).id; } int n_replies = 0; statuses_node.foreach_element ((arr, index, node) => { if (n_replies >= 5) return; var obj = node.get_object (); if (!obj.has_member ("in_reply_to_status_id") || obj.get_null_member ("in_reply_to_status_id")) return; int64 reply_id = obj.get_int_member ("in_reply_to_status_id"); if (reply_id != tweet_id) { return; } Tweet t = new Tweet (); t.load_from_json (node, now, account); if (t.id != previous_tweet_id) { top_list_box.model.add (t); n_replies ++; } }); if (n_replies > 0) { top_list_box.show (); reply_indicator.replies_available = true; } else { //top_list_box.hide (); //reply_indicator.replies_available = false; } }); } //}}} /** * Loads the tweet this tweet is a reply to. * This will recursively call itself until the end of the chain is reached. * * @param reply_id The id of the tweet the previous tweet was a reply to. */ private void load_replied_to_tweet (int64 reply_id) { //{{{ if (reply_id == 0) { return; } bottom_list_box.show (); var call = account.proxy.new_call (); call.set_function ("1.1/statuses/show.json"); call.set_method ("GET"); call.add_param ("id", reply_id.to_string ()); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); }catch (GLib.Error e) { critical(e.message); if (e.message.strip () != "Forbidden") { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } bottom_list_box.visible = (bottom_list_box.get_children ().length () > 0); return; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical (e.message); return; } /* If we get here, the tweet is not protected so we can just use it */ Tweet tweet = new Tweet (); tweet.load_from_json (parser.get_root (), new GLib.DateTime.now_local (), account); bottom_list_box.model.add (tweet); load_replied_to_tweet (tweet.reply_id); }); } //}}} /** * */ private void set_tweet_data (Tweet tweet, string? with = null) {//{{{ account.user_counter.user_seen (tweet.user_id, tweet.screen_name, tweet.user_name); GLib.DateTime created_at = new GLib.DateTime.from_unix_local ( tweet.retweeted_tweet != null ? tweet.retweeted_tweet.created_at : tweet.source_tweet.created_at); string time_format = created_at.format ("%x, %X"); if (with != null) { time_format += " via " + with; } text_label.label = tweet.get_formatted_text (); name_button.set_markup (tweet.user_name); screen_name_label.label = "@" + tweet.screen_name; avatar_image.surface = tweet.avatar; tweet.notify["avatar"].connect (() => { avatar_image.surface = tweet.avatar; }); update_rt_fav_labels (); time_label.label = time_format; retweet_button.active = tweet.retweeted; favorite_button.active = tweet.favorited; avatar_image.verified = tweet.verified; set_source_link (tweet.id, tweet.screen_name); if (tweet.has_inline_media) { mm_widget.set_all_media (tweet.medias); mm_widget.show (); } else { mm_widget.hide (); } if (tweet.user_id == account.id || tweet.protected) { retweet_button.hide (); ((GLib.SimpleAction)actions.lookup_action ("quote")).set_enabled (false); } else { retweet_button.show (); ((GLib.SimpleAction)actions.lookup_action ("quote")).set_enabled (true); } } //}}} private void update_rt_fav_labels () { rt_label.label = "%'d %s".printf (tweet.retweet_count, _("Retweets")); fav_label.label = "%'d %s".printf (tweet.favorite_count, _("Favorites")); } private void set_source_link (int64 id, string screen_name) { var link = "https://twitter.com/%s/status/%s".printf (screen_name, id.to_string ()); source_label.label = "%s" .printf (link, _("Open in Browser"), _("Source")); } private void quote_activated () { ComposeTweetWindow ctw = new ComposeTweetWindow(main_window, this.account, this.tweet, ComposeTweetWindow.Mode.QUOTE); ctw.show (); } public string? get_title () { return _("Tweet Details"); } /** * Twitter's source parameter of tweets includes a 'rel' parameter * that doesn't work as pango markup, so we just remove it here. * * Example string: * TweetDeck * * @param source_str The source string from twitter * * @return The #source_string without the rel parameter */ private string extract_source (string source_str) { //{{{ int from, to; int tmp = 0; tmp = source_str.index_of_char ('"'); tmp = source_str.index_of_char ('"', tmp + 1); from = source_str.index_of_char ('"', tmp + 1); to = source_str.index_of_char ('"', from + 1); if (to == -1 || from == -1) return source_str; return source_str.substring (0, from-5) + source_str.substring(to + 1); } //}}} public void create_tool_button (Gtk.RadioButton? group) {} public Gtk.RadioButton? get_tool_button () { return null; } public void stream_message_received (StreamMessageType type, Json.Node root) { if (type != StreamMessageType.TWEET) return; Json.Object root_obj = root.get_object (); if (Utils.usable_json_value (root_obj, "in_reply_to_status_id")) { int64 reply_id = root_obj.get_int_member ("in_reply_to_status_id"); if (reply_id == this.tweet_id) { Tweet t = new Tweet (); t.load_from_json (root, new GLib.DateTime.now_local (), this.account); top_list_box.model.add (t); top_list_box.show (); this.reply_indicator.replies_available = true; } } } } corebird-1.1/src/Twitter.vala000066400000000000000000000122051260276623600162540ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Twitter : GLib.Object { private static Twitter twitter; public static new Twitter get () { if (twitter == null) twitter = new Twitter (); return twitter; } public Twitter () {} public delegate void AvatarDownloadedFunc (Cairo.Surface avatar); [Signal (detailed = true)] private signal void avatar_downloaded (Cairo.Surface avatar); public static int short_url_length = 22; public static int short_url_length_https = 23; public static int max_media_per_upload = 4; public static Cairo.Surface no_avatar; public static Gdk.Pixbuf no_banner; public Gee.HashMap avatars; public Gee.HashMap avatar_refcounts; /* XXX I'd like this to use a int64->{string, Cairo.Surface} hashtable so we can get the avatar of a specific user but also check if the url changed */ public void init () { try { Twitter.no_avatar = Gdk.cairo_surface_create_from_pixbuf ( new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/no_avatar.png"), 1, null); Twitter.no_banner = new Gdk.Pixbuf.from_resource ("/org/baedert/corebird/assets/no_banner.png"); } catch (GLib.Error e) { error ("Error while loading assets: %s", e.message); } avatars = new Gee.HashMap (); avatar_refcounts = new Gee.HashMap (); } public static void ref_avatar (Cairo.Surface surface) { uint cur = twitter.avatar_refcounts.get (surface); twitter.avatar_refcounts.unset (surface); twitter.avatar_refcounts.set (surface, cur + 1); } public static void unref_avatar (Cairo.Surface surface) { uint cur = twitter.avatar_refcounts.get (surface); uint next = cur - 1; twitter.avatar_refcounts.unset (surface); if (next > 0) twitter.avatar_refcounts.set (surface, next); else { var iter = twitter.avatars.map_iterator (); string? path = null; while (iter.next ()) { if (iter.get_value () == surface) { path = iter.get_key (); break; } } if (path != null) twitter.avatars.unset (path); } } /** * Get the avatar with the given url. If the avatar exists on the * hard drive already, it is loaded and returned immediately. If * the avatar is in memory already, that version is returned. * If the avatar is neither on disk nor in memory, it will be downladed * first and set via the supplied `func`. * * Example usage: * * Gdk.Pixbuf? a = get_avatar("http://foo", (avatar) => { * a = avatar; * }); * (a may be null here) * * @param url The url of the avatar to return * @param func The AvatarDownloadedFunc to call once the avatar has been * downloaded successfully. * * @return The requested avatar if it was already downloaded/in ram, or null * if it has to be downloaded first, in which case the AvatarDownloadedFunc * will be called after that's finished. */ public Cairo.Surface? get_avatar (string url, owned AvatarDownloadedFunc? func = null, int size = 48) { // {{{ Cairo.Surface? a = avatars.get (url); bool has_key = avatars.has_key (url); if (a != null) { return a; } // Someone is already downloading the avatar if (has_key) { // wait until the avatar has finished downloading ulong handler_id = 0; handler_id = this.avatar_downloaded[url].connect ((ava) => { func (ava); this.disconnect (handler_id); }); } else { // download the avatar avatars.set (url, null); TweetUtils.download_avatar.begin (url, size, (obj, res) => { Gdk.Pixbuf? avatar = null; try { avatar = TweetUtils.download_avatar.end (res); } catch (GLib.Error e) { warning (e.message + " for " + url); func (no_avatar); this.avatars.set (url, no_avatar); return; } var s = Gdk.cairo_surface_create_from_pixbuf (avatar, 1, null); func (s); // signal all the other waiters in the queue avatar_downloaded[url](s); this.avatars.set (url, s); this.avatar_refcounts.set (s, 0); }); } // Return null for now, set the actual value in the callback return null; } // }}} //TODO: Add method to update config } corebird-1.1/src/UserCounter.vala000066400000000000000000000071031260276623600170710ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ /* So, this is the plan: we wil just save every single time the user encounters another user. We then save the first 200 or so results and load them on startup. If the user types a name and no result is found, we try to search for that name via Twitter's search API. */ public class UserInfo : GLib.Object { public int64 id; public string screen_name; public string name; public int score; public bool changed; } public class UserCounter : GLib.Object { private bool changed = false; private Gee.ArrayList names = new Gee.ArrayList (); public UserCounter () {} public void id_seen (ref UserIdentity id) { this.user_seen (id.id, id.screen_name, id.user_name); } public void user_seen (int64 id, string screen_name, string name) { // increase the user's seen-count by one bool found = false; this.changed = true; foreach (var ui in names) { if (ui.id == id) { found = true; ui.score ++; //debug ("New score: %d", ui.score); ui.changed = true; break; } } if (!found) { UserInfo ui = new UserInfo (); ui.id = id; ui.screen_name = screen_name; ui.name = name; ui.changed = true; ui.score = 1; names.add(ui); } } public UserInfo[] query_by_prefix (string prefix, int max_results, out int num_results) { int n_results = 0; string p = prefix.down (); UserInfo[] results = new UserInfo[max_results]; foreach (var ui in names) { if (n_results >= max_results) break; if (ui.name.down ().has_prefix (p) || ui.screen_name.down ().has_prefix (p)) { results[n_results] = ui; n_results ++; } } num_results = n_results; return results; } public void load (Sql.Database db) { db.select ("user_cache").cols ("id", "screen_name", "user_name", "score").order ("score DESC").run ((vals) => { UserInfo ui = new UserInfo (); ui.id = int64.parse (vals[0]); ui.screen_name = vals[1]; ui.name = vals[2]; ui.changed = false; ui.score = int.parse (vals[3]); names.add (ui); return true; }); } /** * Saves all the changed user counts into the database. * * @return The number of changes users. */ public int save (Sql.Database db) { if (!changed) return 0; int saved = 0; db.begin_transaction (); foreach (var ui in names) { if (!ui.changed) continue; ui.changed = false; db.replace ("user_cache").vali64 ("id", ui.id) .vali ("score", ui.score) .val ("screen_name", ui.screen_name) .val ("user_name", ui.name) .run(); saved ++; } db.end_transaction (); changed = false; return saved; } } corebird-1.1/src/UserEventReceiver.vala000066400000000000000000000063711260276623600202260ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class UserEventReceiver : GLib.Object, IMessageReceiver { private unowned Account account; public UserEventReceiver (Account account) { this.account = account; } public void stream_message_received (StreamMessageType type, Json.Node root_node) { switch (type) { case StreamMessageType.EVENT_FOLLOW: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.follow_id (user_id); break; case StreamMessageType.EVENT_UNFOLLOW: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.unfollow_id (user_id); break; case StreamMessageType.EVENT_MUTE: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.mute_id (user_id); break; case StreamMessageType.EVENT_UNMUTE: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.unmute_id (user_id); break; case StreamMessageType.EVENT_BLOCK: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.block_id (user_id); break; case StreamMessageType.EVENT_UNBLOCK: int64 user_id = root_node.get_object ().get_object_member ("target") .get_int_member ("id"); account.unblock_id (user_id); break; case StreamMessageType.EVENT_USER_UPDATE: var user_obj = root_node.get_object ().get_object_member ("target"); if (user_obj.get_int_member ("id") == account.id) { string old_screen_name = account.screen_name; account.name = user_obj.get_string_member ("name"); account.description = user_obj.get_string_member ("description"); account.screen_name = user_obj.get_string_member ("screen_name"); account.info_changed (account.screen_name, account.name, account.avatar_small, account.avatar); account.save_info (); Utils.update_startup_account (old_screen_name, account.screen_name); } else warning ("USER_UPDATE: ids don't match"); break; } } } corebird-1.1/src/UserStream.vala000066400000000000000000000227001260276623600167050ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ // See https://dev.twitter.com/docs/streaming-apis/messages public enum StreamMessageType { UNSUPPORTED, DELETE, SCRUB_GEO, LIMIT, DISCONNECT, FRIENDS, EVENT, WARNING, DIRECT_MESSAGE, TWEET, EVENT_LIST_CREATED, EVENT_LIST_DESTROYED, EVENT_LIST_UPDATED, EVENT_LIST_UNSUBSCRIBED, EVENT_LIST_SUBSCRIBED, EVENT_LIST_MEMBER_ADDED, EVENT_LIST_MEMBER_REMOVED, EVENT_FAVORITE, EVENT_UNFAVORITE, EVENT_FOLLOW, EVENT_UNFOLLOW, EVENT_BLOCK, EVENT_UNBLOCK, EVENT_MUTE, EVENT_UNMUTE, EVENT_USER_UPDATE, EVENT_QUOTED_TWEET } public class UserStream : Object { private Rest.OAuthProxy proxy; private Rest.ProxyCall proxy_call; private StringBuilder data = new StringBuilder(); private Gee.ArrayList receivers = new Gee.ArrayList (); private GLib.NetworkMonitor network_monitor; private bool network_available; private uint network_timeout_id = 0; private uint heartbeat_timeout_id = 0; private bool running = false; private string account_name; public string token { set { proxy.token = value; } } public string token_secret { set { proxy.token_secret = value; } } private unowned Account account; // Signals public signal void interrupted (); public signal void resumed (); private bool stopping = false; private bool restarting = false; public UserStream (Account account) { this.account_name = account.screen_name; this.account = account; debug ("CREATING USER STREAM FOR " + account_name); proxy = new Rest.OAuthProxy( Settings.get_consumer_key (), Settings.get_consumer_secret (), "https://userstream.twitter.com/", //Url Format false ); network_monitor = GLib.NetworkMonitor.get_default (); network_available = network_monitor.get_network_available (); network_monitor.network_changed.connect (network_changed_cb); if (!network_available) start_network_timeout (); } public void register (IMessageReceiver receiver) { receivers.add (receiver); } private void network_changed_cb (bool available) { if (available == this.network_available) return; this.network_available = available; if (network_available) { debug ("Restarting stream (reason: Network available (callback))"); restart (); //resumed (); } else { debug ("Connection lost (%s) Reason: network unavailable", account_name); interrupted (); start_network_timeout (); } } /** * Starts the UserStream */ public void start () { debug ("Starting stream for %s", this.account_name); // Reset state of the stream proxy_call = proxy.new_call (); proxy_call.set_function ("1.1/user.json"); proxy_call.set_method ("GET"); start_heartbeat_timeout (); try { proxy_call.continuous (parse_data_cb, proxy_call); } catch (GLib.Error e) { error (e.message); } } /** * Stops the UserStream */ public void stop () { running = false; if (this.network_timeout_id != 0) { GLib.Source.remove (this.network_timeout_id); this.network_timeout_id = 0; } if (this.heartbeat_timeout_id != 0) { GLib.Source.remove (this.heartbeat_timeout_id); this.heartbeat_timeout_id = 0; } stopping = true; debug ("STOPPING STREAM FOR " + account_name); proxy_call.cancel (); stopping = false; } private void restart () { restarting = true; stop (); start (); //restarting = false; } private void start_network_timeout () { if (this.network_timeout_id != 0) return; network_timeout_id = GLib.Timeout.add (1 * 1000, () => { if (running) return GLib.Source.REMOVE; var available = network_monitor.get_network_available (); if (available) { debug ("Restarting stream (reason: network available (timeout))"); this.network_timeout_id = 0; restart (); return GLib.Source.REMOVE; } return GLib.Source.CONTINUE; }); } private void start_heartbeat_timeout () { heartbeat_timeout_id = GLib.Timeout.add (45 * 1000, () => { // If we get here, we need to restart the stream. debug ("Connection lost (%s) Reason: heartbeat. Restarting...", account_name); restart (); return GLib.Source.REMOVE; }); } ~UserStream () { debug ("USERSTREAM for %s DESTROYED", account_name); } /** * Callback called by the Rest.ProxyCall whenever it receives data. * Public for testing only */ public void parse_data_cb (Rest.ProxyCall call, string? buf, size_t length, GLib.Error? error) { if (buf == null) { if (!stopping) { warning ("buf(%s) == NULL. Starting timeout...", this.account_name); this.start_network_timeout (); } return; } string real = buf.substring (0, (int)length); data.append (real); if (real.has_suffix ("\r\n") || real.has_suffix ("\r")) { if (restarting) { resumed (); restarting = false; } if (real == "\r\n") { debug ("HEARTBEAT(%s)", account_name); data.erase (); if (heartbeat_timeout_id != 0) { GLib.Source.remove (heartbeat_timeout_id); heartbeat_timeout_id = 0; } start_heartbeat_timeout (); return; } /* For whatever reason, we sometimes receive "OK" from the server. I can't find an explanation for this but it doesn't seem to cause any harm. */ if (data.str.strip () == "OK") { data.erase (); return; } var parser = new Json.Parser (); try { parser.load_from_data (data.str); } catch (GLib.Error e) { critical (e.message); critical (data.str); data.erase (); return; } running = true; var root_node = parser.get_root(); var root = root_node.get_object (); StreamMessageType type = 0; if (root.has_member ("delete")) type = StreamMessageType.DELETE; else if (root.has_member ("scrub_geo")) type = StreamMessageType.SCRUB_GEO; else if (root.has_member ("limit")) type = StreamMessageType.LIMIT; else if (root.has_member ("disconnect")) type = StreamMessageType.DISCONNECT; else if (root.has_member ("friends")) { account.set_friends (root.get_array_member ("friends")); type = StreamMessageType.FRIENDS; } else if (root.has_member ("text")) type = StreamMessageType.TWEET; else if (root.has_member ("event")) { string evt_str = root.get_string_member ("event"); type = get_event_type (evt_str); } else if (root.has_member ("warning")) type = StreamMessageType.WARNING; else if (root.has_member ("direct_message")) type = StreamMessageType.DIRECT_MESSAGE; else if (root.has_member ("status_withheld")) type = StreamMessageType.UNSUPPORTED; #if DEBUG stdout.printf ("Message with type %s on stream @%s\n", type.to_string (), this.account_name); stdout.printf (data.str+"\n\n"); #endif foreach (IMessageReceiver it in receivers) it.stream_message_received (type, root_node); data.erase (); } } private StreamMessageType get_event_type (string evt_str) { switch (evt_str) { case "follow": return StreamMessageType.EVENT_FOLLOW; case "list_created": return StreamMessageType.EVENT_LIST_CREATED; case "list_destroyed": return StreamMessageType.EVENT_LIST_DESTROYED; case "list_updated": return StreamMessageType.EVENT_LIST_UPDATED; case "list_user_unsubscribed": return StreamMessageType.EVENT_LIST_UNSUBSCRIBED; case "list_user_subscribed": return StreamMessageType.EVENT_LIST_SUBSCRIBED; case "list_member_added": return StreamMessageType.EVENT_LIST_MEMBER_ADDED; case "list_member_removed": return StreamMessageType.EVENT_LIST_MEMBER_REMOVED; case "favorite": return StreamMessageType.EVENT_FAVORITE; case "unfavorite": return StreamMessageType.EVENT_UNFAVORITE; case "unfollow": return StreamMessageType.EVENT_UNFOLLOW; case "block": return StreamMessageType.EVENT_BLOCK; case "unblock": return StreamMessageType.EVENT_UNBLOCK; case "mute": return StreamMessageType.EVENT_MUTE; case "unmute": return StreamMessageType.EVENT_UNMUTE; case "user_update": return StreamMessageType.EVENT_USER_UPDATE; case "quoted_tweet": return StreamMessageType.EVENT_QUOTED_TWEET; } return 0; } } corebird-1.1/src/async/000077500000000000000000000000001260276623600150625ustar00rootroot00000000000000corebird-1.1/src/async/Collect.vala000066400000000000000000000030501260276623600173120ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Collect : GLib.Object { private int cur = 0; private int max; private GLib.Error? error = null; public bool done { get { return this.cur == this.max; } } public signal void finished (GLib.Error? error); public Collect (int max) requires (max >= 0) { this.max = max; } public void emit (GLib.Error? error = null) requires (cur < max) { /* If our global error is set, something previously went wrong and we ignore this call to emit(); */ if (this.error != null) return; /* If error is set, we call finished() with that error and ignore all following calls to emit() */ if (error != null) { finished (error); this.error = error; return; } cur++; if (cur == max) { finished (null); } } } corebird-1.1/src/list/000077500000000000000000000000001260276623600147205ustar00rootroot00000000000000corebird-1.1/src/list/AddListEntry.vala000066400000000000000000000024141260276623600201340ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class AddListEntry : Gtk.ListBoxRow { public AddListEntry (string label) { var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 5); var img = new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.DIALOG); img.pixel_size = 32; img.margin_start = 10; img.hexpand = true; img.halign = Gtk.Align.END; box.pack_start (img); var l = new Gtk.Label (label); l.hexpand = true; l.halign = Gtk.Align.START; box.pack_start (l); box.margin_bottom = 4; box.margin_top = 4; add (box); } } corebird-1.1/src/list/DMListEntry.vala000066400000000000000000000047521260276623600177530ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/dm-list-entry.ui")] class DMListEntry : Gtk.ListBoxRow, ITwitterItem { [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label text_label; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private TextButton name_button; [GtkChild] private Gtk.Label time_delta_label; public string text { set { text_label.label = value; } } public string screen_name { set { screen_name_label.label = "@" + value; } } public new string name { set { name_button.label = value; } } public Cairo.Surface avatar { set { avatar_image.surface = value; } } public bool seen { get { return true; } set {} } public int64 sort_factor { get { return timestamp; } } public string avatar_url; public int64 timestamp; public int64 id; public int64 user_id; public unowned MainWindow main_window; public DMListEntry () { name_button.clicked.connect (() => { var bundle = new Bundle (); bundle.put_int64 ("user_id", user_id); bundle.put_string ("screen_name", screen_name_label.label.substring (1)); main_window.main_widget.switch_page (Page.PROFILE, bundle); }); } public void load_avatar () { avatar_image.surface = Twitter.get ().get_avatar (avatar_url, (a) => { avatar_image.surface = a; }); } public int update_time_delta (GLib.DateTime? now = null) { GLib.DateTime cur_time; if (now == null) cur_time = new GLib.DateTime.now_local (); else cur_time = now; GLib.DateTime then = new GLib.DateTime.from_unix_local (timestamp); time_delta_label.label = Utils.get_time_delta (then, cur_time); return (int)(cur_time.difference (then) / 1000.0 / 1000.0); } } corebird-1.1/src/list/DMThreadEntry.vala000066400000000000000000000055601260276623600202450ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ int dm_thread_entry_sort_func (Gtk.ListBoxRow r1, Gtk.ListBoxRow r2) { if (r1 is StartConversationEntry) return -1; else if (r2 is StartConversationEntry) return 1; if (!(r1 is DMThreadEntry)) return 1; if (((DMThreadEntry)r1).last_message_id > ((DMThreadEntry)r2).last_message_id) return -1; return 1; } [GtkTemplate (ui = "/org/baedert/corebird/ui/dm-thread-entry.ui")] class DMThreadEntry : Gtk.ListBoxRow { public static bool equal_func (DMThreadEntry a, DMThreadEntry b) { return a.user_id == b.user_id; } [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private Gtk.Label last_message_label; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label unread_count_label; public int64 user_id {public get; private set;} public new string name { get { return name_label.label; } set { name_label.label = value; } } public string screen_name { get{ return screen_name_label.label; } set { screen_name_label.label = "@" + value; } } public string last_message { get { return last_message_label.label; } set { last_message_label.label = value; } } public int64 last_message_id {get; set;} public Cairo.Surface avatar { set { avatar_image.surface = value;} owned get { return avatar_image.surface; } } private int _unread_count = 0; public int unread_count { get { return this._unread_count; } set { this._unread_count = value; this.update_unread_count (); } } public string? notification_id = null; public DMThreadEntry (int64 user_id) { this.user_id = user_id; update_unread_count (); } private void update_unread_count () { if (unread_count == 0) unread_count_label.hide (); else { unread_count_label.show (); unread_count_label.label = ngettext ("(%d unread)", "(%d unread)", unread_count).printf(unread_count); } } } corebird-1.1/src/list/FilterListEntry.vala000066400000000000000000000050461260276623600206750ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/filter-list-entry.ui")] class FilterListEntry : Gtk.ListBoxRow { [GtkChild] private Gtk.Label content_label; [GtkChild] private Gtk.Revealer revealer; [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.Grid normal_box; [GtkChild] private Gtk.Box delete_box; private unowned Filter _filter; public unowned Filter filter { set { content_label.label = value.content; _filter = value; } get { return _filter; } } public string content { set { content_label.label = value; } get { return content_label.label; } } private unowned Account account; private unowned MainWindow main_window; public signal void removed (Filter f); public FilterListEntry (Filter f, Account account, MainWindow main_window) { this.filter = f; this.account = account; this.main_window = main_window; } construct { revealer.notify["child-revealed"].connect (() => { if (!revealer.child_revealed) { ((Gtk.Container)this.get_parent ()).remove (this); } }); } [GtkCallback] private void menu_button_clicked_cb () { stack.visible_child = delete_box; this.activatable = false; } [GtkCallback] private void cancel_button_clicked_cb () { stack.visible_child = normal_box; this.activatable = true; } [GtkCallback] private void delete_button_clicked_cb () { foreach (Filter f in account.filters) { if (f.id == this.filter.id) { account.filters.remove (f); account.db.exec ("DELETE FROM `filters` WHERE `id`='%d'".printf (f.id)); //removed (f); revealer.reveal_child = false; main_window.rerun_filters (); return; } } } } corebird-1.1/src/list/ListListEntry.vala000066400000000000000000000125541260276623600203650ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/list-list-entry.ui")] public class ListListEntry : Gtk.ListBoxRow { public static int sort_func (Gtk.ListBoxRow r1, Gtk.ListBoxRow r2) { if (!(r1 is ListListEntry)) return -1; return ((ListListEntry)r1).name.ascii_casecmp (((ListListEntry)r2).name); } [GtkChild] private Gtk.Label name_label; public new string name { set { name_label.label = normalize_name (value); } get { return name_label.label; } } [GtkChild] private Gtk.Label description_label; public string description { set { description_label.label = value; } get { return description_label.label; } } [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.Button subscribe_button; [GtkChild] private Gtk.Button unsubscribe_button; [GtkChild] private Gtk.Button delete_button; [GtkChild] private Gtk.Button cancel_button; public int64 id; public bool user_list = false; public string creator_screen_name; public int n_subscribers; public int n_members = 0; public int64 created_at; public string mode; private unowned Account account; public ListListEntry.from_json_data (Json.Object obj, Account account) { this.account = account; var user = obj.get_object_member ("user"); name = normalize_name (obj.get_string_member ("full_name")); description = obj.get_string_member ("description"); id = obj.get_int_member ("id"); creator_screen_name = user.get_string_member ("screen_name"); n_subscribers = (int)obj.get_int_member ("subscriber_count"); n_members = (int)obj.get_int_member ("member_count"); created_at = Utils.parse_date (obj.get_string_member ("created_at")).to_unix (); mode = obj.get_string_member ("mode"); bool following = obj.get_boolean_member ("following"); if (following || user.get_int_member ("id") == account.id) { unsubscribe_button.show (); subscribe_button.hide (); } else { unsubscribe_button.hide (); subscribe_button.show (); } if (user.get_int_member ("id") == account.id) { user_list = true; unsubscribe_button.hide (); } else { delete_button.hide (); } } private string normalize_name (string name) { if (name.contains ("/lists/")) { return name.replace ("/lists/", "/"); } return name; } [GtkCallback] private void delete_button_clicked_cb () { this.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/lists/destroy.json"); call.set_method ("POST"); call.add_param ("list_id", id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } }); } [GtkCallback] private void subscribe_button_clicked_cb () { subscribe_button.sensitive = false; cancel_button.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/lists/subscribers/create.json"); call.set_method ("POST"); call.add_param ("list_id", id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } finally { subscribe_button.sensitive = true; cancel_button.sensitive = true; } subscribe_button.hide (); unsubscribe_button.show (); }); } [GtkCallback] private void unsubscribe_button_clicked_cb () { this.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/lists/subscribers/destroy.json"); call.set_method ("POST"); call.add_param ("list_id", id.to_string ()); call.invoke_async.begin (null, (o, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); return; } }); } [GtkCallback] private void more_button_clicked_cb () { stack.visible_child_name = "more"; this.activatable = false; } [GtkCallback] private void cancel_button_clicked_cb () { stack.visible_child_name = "default"; this.activatable = true; } [GtkCallback] private bool focus_out_cb () { stack.visible_child_name = "default"; return false; } } corebird-1.1/src/list/NewListEntry.vala000066400000000000000000000025611260276623600202000ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/new-list-entry.ui")] class NewListEntry : Gtk.ListBoxRow { [GtkChild] private Gtk.Entry list_name_entry; [GtkChild] private Gtk.Revealer revealer; public signal void create_activated (string list_name); public void reveal () { revealer.reveal_child = true; this.activatable = false; list_name_entry.grab_focus (); } public void unreveal () { revealer.reveal_child = false; this.activatable = true; list_name_entry.text = ""; } [GtkCallback] private void create_list_button_clicked_cb () { create_activated (list_name_entry.text); } } corebird-1.1/src/list/ProgressEntry.vala000066400000000000000000000031431260276623600204140ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class ProgressEntry : Gtk.ListBoxRow, ITwitterItem { public int64 sort_factor { get { return 0; } } public bool seen { get { return true; } set {} } public ProgressEntry () { this.activatable = false; Gtk.Spinner spinner = new Gtk.Spinner (); Gtk.Label l = new Gtk.Label (_("Loading more data...")); Gtk.Box box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); l.set_halign (Gtk.Align.START); l.hexpand = true; spinner.set_size_request (16, 16); spinner.set_halign (Gtk.Align.END); spinner.set_valign (Gtk.Align.CENTER); spinner.margin_top = 12; spinner.margin_bottom = 12; spinner.hexpand = true; spinner.start (); box.pack_start (spinner, true, true); box.pack_start (l, true, true); this.add (box); } public int update_time_delta (GLib.DateTime? now = null) { return 0; } } corebird-1.1/src/list/SnippetListEntry.vala000066400000000000000000000040711260276623600210670ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class SnippetListEntry : Gtk.ListBoxRow { private Gtk.Label key_label; private Gtk.Label value_label; private Gtk.Revealer revealer; public string key { get { return key_label.label; } set { key_label.label = value; } } public string value { get { return value_label.label; } set { value_label.label = value; } } public SnippetListEntry (string key, string value) { this.revealer = new Gtk.Revealer (); revealer.reveal_child = true; var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); box.margin = 6; box.homogeneous = true; key_label = new Gtk.Label (key); key_label.halign = Gtk.Align.START; key_label.hexpand = true; key_label.ellipsize = Pango.EllipsizeMode.END; box.add (key_label); value_label = new Gtk.Label (value); value_label.halign = Gtk.Align.START; value_label.hexpand = true; value_label.xalign = 0; value_label.ellipsize = Pango.EllipsizeMode.END; box.add (value_label); revealer.add (box); this.add (revealer); this.get_style_context ().add_class ("tweet"); } public void reveal () { revealer.notify["child-revealed"].connect (() => { if (!revealer.child_revealed) { this.get_parent ().remove (this); } }); revealer.reveal_child = false; } } corebird-1.1/src/list/StartConversationEntry.vala000066400000000000000000000154251260276623600223060ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/start-conversation-entry.ui")] class StartConversationEntry : Gtk.ListBoxRow { private static const int MAX_RESULTS = 7; [GtkChild] private Gtk.Revealer revealer; [GtkChild] private ReplyEntry name_entry; [GtkChild] private Gtk.Stack go_stack; [GtkChild] private Gtk.Spinner go_spinner; private UserCompletion user_completion; private Gtk.Window completion_window = new Gtk.Window (Gtk.WindowType.POPUP); private Gtk.ListBox completion_list = new Gtk.ListBox (); private int current_match = -1; public signal void start (int64 user_id, string screen_name, string name, string avatar_url); private unowned Account account; public StartConversationEntry (Account account) { this.account = account; completion_window.set_type_hint (Gdk.WindowTypeHint.COMBO); completion_window.set_attached_to (name_entry); completion_window.set_screen (name_entry.get_screen ()); completion_window.destroy_with_parent = true; completion_window.focus_out_event.connect (() => { completion_window.hide (); return false; }); name_entry.focus_out_event.connect (() => { completion_window.hide (); return false; }); var popup_frame = new Gtk.Frame (null); var scroller = new Gtk.ScrolledWindow (null, null); popup_frame.add (scroller); scroller.add (completion_list); completion_window.add (popup_frame); completion_list.activate_on_single_click = false; completion_list.row_activated.connect (go_button_clicked_cb); user_completion = new UserCompletion (account, MAX_RESULTS); user_completion.connect_to (name_entry.buffer, "text"); user_completion.start_completion.connect (() => { completion_window.show_all (); position_popup_window (); completion_list.foreach ((w) => { completion_list.remove (w); }); }); user_completion.populate_completion.connect ((name, screen_name) => { var l = new CompletionListEntry (name, screen_name); l.show_all (); completion_list.add (l); }); name_entry.key_press_event.connect (name_entry_key_pressed); // activate.connect (() => { // go_stack.visible_child_name = "spinner"; // go_spinner.start (); // }); } private void position_popup_window () { // {{{ int x, y; Gtk.Allocation alloc; name_entry.get_allocation (out alloc); name_entry.get_window ().get_origin (out x, out y); x += alloc.x; y += alloc.y + alloc.height; completion_window.move (x, y); completion_window.resize (alloc.width, 50); } // }}} private bool name_entry_key_pressed (Gdk.EventKey evt) { uint num_results = completion_list.get_children ().length (); if (evt.keyval == Gdk.Key.Down) { current_match = (current_match + 1) % (int)num_results; var row = completion_list.get_row_at_index (current_match); completion_list.select_row (row); return true; } else if (evt.keyval == Gdk.Key.Up) { current_match --; if (current_match < 0) current_match = (int)num_results - 1; var row = completion_list.get_row_at_index (current_match); completion_list.select_row (row); return true; } else if (evt.keyval == Gdk.Key.Return) { } return false; } construct { name_entry.cancelled.connect (() => { unreveal (); this.grab_focus (); }); } public void reveal () { revealer.reveal_child = true; name_entry.grab_focus (); this.activatable = false; } public void unreveal () { revealer.reveal_child = false; completion_window.hide (); this.activatable = true; } [GtkCallback] private void go_button_clicked_cb () { // {{{ // if (name_entry.text.length > 0) // activated (); string screen_name; if (completion_list.get_selected_row () != null) { screen_name = ((CompletionListEntry)completion_list.get_selected_row ()).get_screen_name (); name_entry.text = screen_name; } else screen_name = name_entry.text; if (screen_name.has_prefix ("@")) screen_name = screen_name.substring (1); if (screen_name.length <= 0) return; go_stack.visible_child_name = "spinner"; go_spinner.start(); name_entry.sensitive = false; var call = account.proxy.new_call (); call.set_function ("1.1/users/show.json"); call.set_method ("GET"); call.add_param ("include_entities", "false"); call.add_param ("screen_name", screen_name); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { critical (e.message); go_stack.visible_child_name = "button"; name_entry.sensitive = true; return; } // do stuff Json.Parser parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { critical (e.message); return; } var root = parser.get_root ().get_object (); int64 user_id = root.get_int_member ("id"); string name = root.get_string_member ("name"); string avatar_url = root.get_string_member ("profile_image_url"); start (user_id, screen_name, name, avatar_url); name_entry.sensitive = true; go_stack.visible_child_name = "button"; }); } } /// }}} class CompletionListEntry : Gtk.ListBoxRow { private Gtk.Label name_label = new Gtk.Label (""); private Gtk.Label screen_name_label = new Gtk.Label (""); public CompletionListEntry (string screen_name, string name) { var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); name_label.label = name; name_label.ellipsize = Pango.EllipsizeMode.END; screen_name_label.label = "@" + screen_name; name_label.set_valign (Gtk.Align.BASELINE); screen_name_label.set_valign (Gtk.Align.BASELINE); screen_name_label.get_style_context ().add_class ("dim-label"); box.pack_start (name_label, false, false); box.pack_start (screen_name_label, false, false); add (box); } public string get_screen_name () { return screen_name_label.get_label ().substring (1); } } corebird-1.1/src/list/TweetListEntry.vala000066400000000000000000000347151260276623600205450ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/tweet-list-entry.ui")] public class TweetListEntry : ITwitterItem, Gtk.ListBoxRow { private const GLib.ActionEntry[] action_entries = { {"quote", quote_activated}, {"delete", delete_activated} }; private const int64 TRANSITION_DURATION = 300; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private TextButton name_button; [GtkChild] private Gtk.Label time_delta_label; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Label text_label; [GtkChild] private Gtk.Label rt_label; [GtkChild] private Gtk.Image rt_image; [GtkChild] private Gtk.Image conversation_image; [GtkChild] private Gtk.Image rt_status_image; [GtkChild] private Gtk.Image fav_status_image; [GtkChild] private DoubleTapButton retweet_button; [GtkChild] private Gtk.ToggleButton favorite_button; [GtkChild] private Gtk.Grid grid; [GtkChild] private MultiMediaWidget mm_widget; [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.Box action_box; [GtkChild] private Gtk.Label quote_label; [GtkChild] private TextButton quote_name; [GtkChild] private Gtk.Label quote_screen_name; [GtkChild] private Gtk.Grid quote_grid; private bool _read_only = false; public bool read_only { set { mm_widget.sensitive = !value; name_button.read_only = value; this._read_only = value; } } public new bool visible { get { return !this.tweet.is_hidden; } set { base.visible = value; } } public int64 sort_factor { get { return tweet.source_tweet.id;} } public bool shows_actions { get { return stack.visible_child == action_box; } } private weak Account account; private weak MainWindow main_window; public Tweet tweet; private bool values_set = false; private bool delete_first_activated = false; [Signal (action = true)] private signal void reply_tweet (); [Signal (action = true)] private signal void favorite_tweet (); [Signal (action = true)] private signal void retweet_tweet (); [Signal (action = true)] private signal void delete_tweet (); public TweetListEntry (owned Tweet tweet, MainWindow? main_window, Account account) { this.account = account; this.tweet = tweet; this.main_window = main_window; name_button.set_markup (tweet.user_name); screen_name_label.label = "@" + tweet.screen_name; avatar_image.surface = tweet.avatar; avatar_image.verified = tweet.verified; text_label.label = tweet.get_trimmed_text (); update_time_delta (); if (tweet.retweeted_tweet != null) { rt_label.show (); rt_image.show (); rt_label.label = @"" + @"$(tweet.source_tweet.author.user_name)"; } else { grid.remove (rt_image); grid.remove (rt_label); } if (tweet.quoted_tweet != null) { quote_label.label = TextTransform.transform_tweet (tweet.quoted_tweet, Settings.get_text_transform_flags ()); quote_name.set_markup (tweet.quoted_tweet.author.user_name); quote_screen_name.label = "@" + tweet.quoted_tweet.author.screen_name; quote_grid.show (); quote_grid.show_all (); } retweet_button.active = tweet.retweeted; retweet_button.sensitive = (tweet.user_id != account.id) && !tweet.protected; tweet.notify["retweeted"].connect (retweeted_cb); favorite_button.active = tweet.favorited; tweet.notify["favorited"].connect (favorited_cb); tweet.hidden_flags_changed.connect (hidden_flags_changed_cb); tweet.notify["deleted"].connect (tweet_deleted_cb); if (tweet.reply_id == 0) conversation_image.unparent (); else { conversation_image.show (); } // If the avatar gets loaded, we want to change it here immediately tweet.notify["avatar"].connect (avatar_changed); if (tweet.has_inline_media) { mm_widget.set_all_media (tweet.medias); mm_widget.media_clicked.connect (media_clicked_cb); mm_widget.media_invalid.connect (media_invalid_cb); mm_widget.window = main_window; } else grid.remove (mm_widget); var actions = new GLib.SimpleActionGroup (); actions.add_action_entries (action_entries, this); this.insert_action_group ("tweet", actions); if (tweet.user_id != account.id) ((GLib.SimpleAction)actions.lookup_action ("delete")).set_enabled (false); if (tweet.user_id == account.id || tweet.protected) ((GLib.SimpleAction)actions.lookup_action ("quote")).set_enabled (false); reply_tweet.connect (reply_tweet_activated); delete_tweet.connect (delete_tweet_activated); favorite_tweet.connect (() => { if (favorite_button.parent != null) favorite_button.active = !favorite_button.active; }); retweet_tweet.connect (() => { retweet_button.tap (); }); if (tweet.favorited) fav_status_image.show (); if (tweet.retweeted) rt_status_image.show (); values_set = true; Settings.get ().changed["text-transform-flags"].connect (transform_flags_changed_cb); } ~TweetListEntry () { Settings.get ().changed["text-transform-flags"].disconnect (transform_flags_changed_cb); } private void transform_flags_changed_cb () { text_label.label = tweet.get_trimmed_text (); if (this.tweet.quoted_tweet != null) { this.quote_label.label = TextTransform.transform_tweet (tweet.quoted_tweet, Settings.get_text_transform_flags ()); } } private void favorited_cb () { values_set = false; favorite_button.active = tweet.favorited; fav_status_image.visible = tweet.favorited; values_set = true; } private void retweeted_cb () { values_set = false; retweet_button.active = tweet.retweeted; rt_status_image.visible = tweet.retweeted; values_set = true; } private void media_clicked_cb (Media m, int index) { TweetUtils.handle_media_click (this.tweet, this.main_window, index); } private void delete_tweet_activated () { if (tweet.user_id != account.id) return; // Nope. if (delete_first_activated) { TweetUtils.delete_tweet.begin (account, tweet, () => { sensitive = false; }); } else delete_first_activated = true; } private void avatar_changed () { avatar_image.surface = tweet.avatar; } static construct { unowned Gtk.BindingSet binding_set = Gtk.BindingSet.by_class ((GLib.ObjectClass)typeof (TweetListEntry).class_ref ()); Gtk.BindingEntry.add_signal (binding_set, Gdk.Key.r, 0, "reply-tweet", 0, null); Gtk.BindingEntry.add_signal (binding_set, Gdk.Key.d, 0, "delete-tweet", 0, null); Gtk.BindingEntry.add_signal (binding_set, Gdk.Key.t, 0, "retweet-tweet", 0, null); Gtk.BindingEntry.add_signal (binding_set, Gdk.Key.f, 0, "favorite-tweet", 0, null); } [GtkCallback] private bool focus_out_cb (Gdk.EventFocus evt) { delete_first_activated = false; retweet_button.reset (); return false; } [GtkCallback] private bool key_released_cb (Gdk.EventKey evt) { #if DEBUG switch(evt.keyval) { case Gdk.Key.k: stdout.printf (tweet.json_data+"\n"); return true; } #endif return false; } /** * Retweets or un-retweets the tweet. */ [GtkCallback] private void retweet_button_toggled_cb () { /* You can't retweet your own tweets. */ if (account.id == this.tweet.user_id || !values_set) { retweet_button.active = false; return; } retweet_button.sensitive = false; TweetUtils.toggle_retweet_tweet.begin (account, tweet, !retweet_button.active, () => { retweet_button.sensitive = true; }); if (shows_actions) toggle_mode (); } [GtkCallback] private void favorite_button_toggled_cb () { if (!values_set) return; favorite_button.sensitive = false; TweetUtils.toggle_favorite_tweet.begin (account, tweet, !favorite_button.active, () => { favorite_button.sensitive = true; }); if (shows_actions) toggle_mode (); } [GtkCallback] private void name_button_clicked_cb () { int64 user_id; string screen_name; if (tweet.retweeted_tweet != null) { user_id = tweet.retweeted_tweet.author.id; screen_name = tweet.retweeted_tweet.author.screen_name; } else { user_id = tweet.source_tweet.author.id; screen_name = tweet.source_tweet.author.screen_name; } var bundle = new Bundle (); bundle.put_int64 ("user_id", user_id); bundle.put_string ("screen_name", screen_name); main_window.main_widget.switch_page (Page.PROFILE, bundle); } [GtkCallback] private void quote_name_button_clicked_cb () { assert (tweet.quoted_tweet != null); var bundle = new Bundle (); bundle.put_int64 ("user_id", tweet.quoted_tweet.author.id); bundle.put_string ("screen_name", tweet.quoted_tweet.author.screen_name); main_window.main_widget.switch_page (Page.PROFILE, bundle); } [GtkCallback] private void reply_button_clicked_cb () { ComposeTweetWindow ctw = new ComposeTweetWindow (this.main_window, this.account, this.tweet, ComposeTweetWindow.Mode.REPLY); ctw.show (); if (shows_actions) toggle_mode (); } private void quote_activated () { ComposeTweetWindow ctw = new ComposeTweetWindow (this.main_window, this.account, this.tweet, ComposeTweetWindow.Mode.QUOTE); ctw.show (); toggle_mode (); } private void reply_tweet_activated () { ComposeTweetWindow ctw = new ComposeTweetWindow (this.main_window, this.account, this.tweet, ComposeTweetWindow.Mode.REPLY); ctw.show (); } private void delete_activated () { delete_first_activated = true; delete_tweet (); toggle_mode (); } [GtkCallback] private bool link_activated_cb (string uri) { if (this._read_only) { return false; } this.grab_focus (); return TweetUtils.activate_link (uri, main_window); } [GtkCallback] private void populate_popup_cb (Gtk.Label source, Gtk.Menu menu) { var link_text = source.get_current_uri (); if (link_text.has_prefix ("#")) { var item = new Gtk.MenuItem.with_label (_("Block %s").printf (link_text)); item.show (); item.activate.connect (() => { Utils.create_persistent_filter (link_text, account); main_window.rerun_filters (); }); menu.add (item); } } private void media_invalid_cb () { TransformFlags flags = Settings.get_text_transform_flags () & ~TransformFlags.REMOVE_MEDIA_LINKS; string new_text = TextTransform.transform_tweet (tweet.retweeted_tweet ?? tweet.source_tweet, flags); this.text_label.label = new_text; if (tweet.quoted_tweet != null) { string new_quote_text = TextTransform.transform_tweet (tweet.quoted_tweet, flags); this.quote_label.label = new_quote_text; } } private void hidden_flags_changed_cb () { if (tweet.is_hidden) this.hide (); else this.show (); } private void tweet_deleted_cb () { #if DEBUG assert (this.sensitive != tweet.deleted); #endif this.sensitive = !tweet.deleted; stack.visible_child = grid; } /** * Updates the time delta label in the upper right * * @return The seconds between the current time and * the time the tweet was created */ public int update_time_delta (GLib.DateTime? now = null) { //{{{ GLib.DateTime cur_time; if (now == null) cur_time = new GLib.DateTime.now_local (); else cur_time = now; GLib.DateTime then = new GLib.DateTime.from_unix_local ( tweet.retweeted_tweet != null ? tweet.retweeted_tweet.created_at : tweet.source_tweet.created_at); //tweet.is_retweet ? tweet.rt_created_at : tweet.created_at); time_delta_label.label = Utils.get_time_delta (then, cur_time); return (int)(cur_time.difference (then) / 1000.0 / 1000.0); } //}}} public void toggle_mode () { if (this._read_only) return; if (stack.visible_child == action_box) { stack.visible_child = grid; this.activatable = true; } else { stack.visible_child = action_box; this.activatable = false; } } private int64 start_time; private int64 end_time; private double ease_out_cubic (double t) { double p = t - 1; return p * p * p +1; } private bool anim_tick (Gtk.Widget widget, Gdk.FrameClock frame_clock) { int64 now = frame_clock.get_frame_time (); if (now > end_time) { this.opacity = 1.0; return false; } double t = (now - start_time) / (double)(end_time - start_time); t = ease_out_cubic (t); this.opacity = t; return true; } public void fade_in () { if (this.get_realized ()) { this.show (); return; } ulong realize_id = 0; realize_id = this.realize.connect (() => { this.start_time = this.get_frame_clock ().get_frame_time (); this.end_time = start_time + (TRANSITION_DURATION * 1000); this.add_tick_callback (anim_tick); this.disconnect (realize_id); }); this.show (); } public override void show () { if (tweet.is_hidden) return; base.show (); } } corebird-1.1/src/list/UserFilterEntry.vala000066400000000000000000000043061260276623600206760ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/user-filter-entry.ui")] class UserFilterEntry : Gtk.ListBoxRow, ITwitterItem { [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Stack stack; [GtkChild] private Gtk.Box delete_box; [GtkChild] private Gtk.Grid grid; [GtkChild] private Gtk.Revealer revealer; public new string name { set { name_label.label = value; } } public string screen_name { set { screen_name_label.label = "@" + value; } } public string avatar { set { real_set_avatar (value); } } public bool seen { get { return true; } set {} } public int64 sort_factor { get{ return 2; } } public int64 user_id { get; set; } public signal void deleted (int64 id); private void real_set_avatar (string avatar_url) { avatar_image.surface = Twitter.get ().get_avatar (avatar_url, (a) => { avatar_image.surface = a; }); } public int update_time_delta (GLib.DateTime? now = null) {return 0;} [GtkCallback] private void menu_button_clicked_cb () { stack.visible_child = delete_box; } [GtkCallback] private void cancel_button_clicked_cb () { stack.visible_child = grid; } [GtkCallback] private void delete_button_clicked_cb () { revealer.reveal_child = false; revealer.notify["child-revealed"].connect (() => { deleted (user_id); }); } } corebird-1.1/src/list/UserListEntry.vala000066400000000000000000000100461260276623600203620ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ [GtkTemplate (ui = "/org/baedert/corebird/ui/user-list-entry.ui")] class UserListEntry : Gtk.ListBoxRow, ITwitterItem { [GtkChild] private Gtk.Label name_label; [GtkChild] private Gtk.Label screen_name_label; [GtkChild] private AvatarWidget avatar_image; [GtkChild] private Gtk.Button settings_button; [GtkChild] private Gtk.Button new_window_button; public new string name { set { name_label.label = value; } } public string screen_name { set { screen_name_label.label = value; } owned get { return screen_name_label.label.substring (1); } } public string avatar { set { real_set_avatar (value); } } public Cairo.Surface avatar_surface { set { avatar_image.surface = value; } } public bool seen { get { return true; } set {} } public int64 sort_factor { get{ return int64.MAX-1; } } public bool show_settings { set { settings_button.visible = value; new_window_button.visible = value; } } public int64 user_id { get; set; } public signal void action_clicked (); private unowned Account account; public UserListEntry.from_account (Account acc) { this.screen_name = "@" + acc.screen_name; this.name = acc.name; this.avatar_surface = acc.avatar; this.account = acc; this.user_id = acc.id; acc.info_changed.connect ((screen_name, name, nop, avatar) => { this.screen_name = "@" + screen_name; this.name = name; this.avatar_surface = avatar; }); acc.notify["avatar"].connect (() => { this.avatar_surface = acc.avatar; }); var cb = (Corebird) GLib.Application.get_default (); cb.window_added.connect ((window) => { if (window is MainWindow) { update_window_button_sensitivity (window, false); } }); cb.window_removed.connect ((window) => { if (window is MainWindow) { update_window_button_sensitivity (window, true); } }); cb.account_window_changed.connect ((old_id, new_id) => { if (old_id == this.user_id) new_window_button.sensitive = true; else if (new_id == this.user_id) new_window_button.sensitive = false; }); // Set initial sensitivitiy of new_window_button new_window_button.sensitive = !(cb.is_window_open_for_user_id (acc.id)); } private void real_set_avatar (string avatar_url) { avatar_image.surface = Twitter.get ().get_avatar (avatar_url, (a) => { avatar_image.surface = a; }); } public int update_time_delta (GLib.DateTime? now = null) {return 0;} private void update_window_button_sensitivity (Gtk.Window window, bool new_value) { if (((MainWindow)window).account.screen_name == this.account.screen_name) { new_window_button.sensitive = new_value; } } [GtkCallback] private void settings_button_clicked_cb () { action_clicked (); var active_window = ((Gtk.Application)GLib.Application.get_default ()).active_window; var dialog = new AccountDialog (this.account); dialog.set_transient_for (active_window); dialog.modal = true; dialog.show (); } [GtkCallback] private void new_window_button_clicked_cb () { var cb = (Corebird) GLib.Application.get_default (); var window = new MainWindow (cb, this.account); cb.add_window (window); window.show_all (); action_clicked (); } } corebird-1.1/src/main.vala000066400000000000000000000017711260276623600155440ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ int main (string[] args) { #if VIDEO Gst.init (ref args); #endif try { //no initialisation of static fields :( Settings.init (); var corebird = new Corebird (); return corebird.run (args); } catch (GLib.Error e) { error (e.message); } } corebird-1.1/src/model/000077500000000000000000000000001260276623600150455ustar00rootroot00000000000000corebird-1.1/src/model/TweetModel.vala000066400000000000000000000123631260276623600177700ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class TweetModel : GLib.Object, GLib.ListModel { private Gee.ArrayList tweets = new Gee.ArrayList (); private int64 min_id = int64.MAX; private int64 max_id = int64.MIN; public int64 lowest_id { get { return min_id; } } public int64 greatest_id { get { return max_id; } } public GLib.Type get_item_type () { return typeof (Tweet); } public GLib.Object? get_item (uint index) { assert (index >= 0); assert (index < tweets.size); return tweets.get ((int)index); } public uint get_n_items () { return tweets.size; } private void insert_sorted (Tweet tweet) { /* Determine the end we start at. Higher IDs are at the beginning of the list */ int insert_pos = -1; if (tweet.id > max_id) { insert_pos = 0; } else if (tweet.id < min_id) { insert_pos = tweets.size; } else { // This case is weird(?), but just estimate the starting point int64 half = (max_id - min_id) / 2; if (tweet.id > min_id + half) { // we start at the beginning for (int i = 0, p = tweets.size; i < p; i ++) { if (tweets.get (i).id < tweet.id) { insert_pos = i; break; } } } else { // we start at the end for (int i = tweets.size - 1; i >= 0; i --) { if (tweets.get (i).id <= tweet.id) { insert_pos = i; break; } } } } assert (insert_pos != -1); tweets.insert (insert_pos, tweet); this.items_changed (insert_pos, 0, 1); } public void add (Tweet tweet) { this.insert_sorted (tweet); if (tweet.id > this.max_id) this.max_id = tweet.id; if (tweet.id < this.min_id) this.min_id = tweet.id; } public void remove_last_n_visible (uint amount) { assert (amount < tweets.size); uint n_removed = 0; int index = tweets.size - 1; while (index >= 0 && n_removed < amount) { Tweet tweet = tweets.get (index); if (!tweet.is_hidden) n_removed ++; tweets.remove_at (index); index --; } this.items_changed (tweets.size - 1, n_removed, 0); } public void clear () { int s = this.tweets.size; this.tweets.clear (); this.min_id = int64.MAX; this.max_id = int64.MIN; this.items_changed (0, s, 0); } public void remove (int64 tweet_id) { for (int i = 0, p = tweets.size; i < p; i ++) { if (tweets.get(i).id == tweet_id) { tweets.remove_at (i); this.items_changed (i, 1, 0); break; } } } public void remove_tweet (Tweet t) { #if DEBUG assert (this.contains_id (t.id)); #endif int pos = this.tweets.index_of (t); this.tweets.remove (t); this.items_changed (pos, 1, 0); } public void toggle_flag_on_tweet (int64 user_id, uint reason, bool active) { foreach (Tweet tweet in tweets) { if (tweet.user_id == user_id) { if (active) tweet.hidden_flags |= reason; else tweet.hidden_flags &= ~reason; tweet.hidden_flags_changed (); } } } public void toggle_flag_on_retweet (int64 user_id, uint reason, bool active) { foreach (Tweet tweet in tweets) { if (tweet.retweeted_tweet != null && tweet.source_tweet.author.id == user_id) { if (active) tweet.hidden_flags |= reason; else tweet.hidden_flags &= ~reason; tweet.hidden_flags_changed (); } } } public bool contains_id (int64 tweet_id) { foreach (Tweet t in tweets) if (t.id == tweet_id) return true; return false; } public void remove_tweets_above (int64 id) { while (tweets.size > 0 && tweets.get (0).id >= id) { tweets.remove_at (0); this.items_changed (0, 1, 0); } } public Tweet? get_from_id (int64 id, int diff) { for (int i = 0; i < tweets.size; i ++) { if (tweets.get (i).id == id) { if (i + diff < tweets.size && i + diff >= 0) return tweets.get (i + diff); return null; } } return null; } public bool delete_id (int64 id, out bool seen) { for (int i = 0; i < tweets.size; i ++) { Tweet t = tweets.get (i); if (t.id == id) { seen = t.seen; if (t.is_hidden) this.remove_tweet (t); else t.deleted = true; return true; } else if (t.retweeted && t.my_retweet == id) { t.retweeted = false; } } seen = false; return false; } } corebird-1.1/src/sql/000077500000000000000000000000001260276623600145445ustar00rootroot00000000000000corebird-1.1/src/sql/Database.vala000066400000000000000000000067351260276623600171300ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace Sql { public const string COREBIRD_INIT_FILE = DATADIR + "/sql/init/Create.%d.sql"; public const string ACCOUNTS_INIT_FILE = DATADIR + "/sql/accounts/Create.%d.sql"; public const int STOP = -1; public const int CONTINUE = 0; public class Database { private Sqlite.Database db; public Database (string filename, string? init_file = null) { int err = Sqlite.Database.open (filename, out db); if (err == 1) { critical ("Error when opening the database '%s': %s", filename, db.errmsg ()); } this.exec ("PRAGMA journal_mode = MEMORY;"); if (init_file == null) return; int user_version = -1; this.exec ("pragma user_version;", (n_cols, vals) => {user_version = int.parse(vals[0]); return STOP;}); var next_version_file = init_file.printf(user_version + 1); debug ("%s User version: %d", filename, user_version); while (FileUtils.test (next_version_file, FileTest.EXISTS)) { string sql_content; try { debug ("Applying file '%s'", next_version_file); FileUtils.get_contents (next_version_file, out sql_content); } catch (GLib.FileError e) { critical (e.message); return; } db.exec (sql_content); debug ("Executed init file '%s' for database '%s'", next_version_file, filename); this.exec ("pragma user_version;", (n_cols, vals) => {user_version = int.parse(vals[0]); return STOP;}); next_version_file = init_file.printf (user_version + 1); } } public int64 exec_insert (string sql) { db.exec (sql); return db.last_insert_rowid (); } public void exec (string sql, Sqlite.Callback? callback = null) { #if DEBUG string err = ""; int val = db.exec (sql, callback, out err); if (val != Sqlite.OK && val != 4) critical ("SQL ERROR(%d): '%s' FOR QUERY '%s'", val, err, sql); #else db.exec (sql, callback); #endif } public void execf (string sql, string first_param, ...) { db.exec (sql.printf (first_param, va_list ())); } public Sql.InsertStatement insert (string table_name) { var stmt = new InsertStatement (table_name); stmt.db = db; return stmt; } public Sql.InsertStatement replace (string table_name) { var stmt = new InsertStatement (table_name, true); stmt.db = db; return stmt; } public Sql.SelectStatement select (string table_name) { var stmt = new SelectStatement (table_name); stmt.db = db; return stmt; } public Sql.UpdateStatement update (string table_name) { var stmt = new UpdateStatement (table_name); stmt.db = db; return stmt; } public void begin_transaction () { db.exec ("BEGIN TRANSACTION;"); } public void end_transaction () { db.exec ("END TRANSACTION;"); } } } corebird-1.1/src/sql/SelectStatement.vala000066400000000000000000000055131260276623600205210ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace Sql { public class SelectStatement : IStatement { public unowned Sqlite.Database db { public set; private get; } private StringBuilder query_builder = new StringBuilder (); private string table_name; public SelectStatement (string table_name) { this.table_name = table_name; } public SelectStatement cols (string first, ...) { var arg_list = va_list (); query_builder.append ("SELECT `").append (first).append ("`"); for (string? arg = arg_list.arg (); arg != null; arg = arg_list.arg ()) { query_builder.append (", `").append (arg).append ("`"); } query_builder.append (" FROM `").append (table_name).append ("`"); return this; } public SelectStatement where (string stmt) { query_builder.append (" WHERE ").append (stmt); return this; } public SelectStatement where_eqi (string w, int64 v) { query_builder.append (" WHERE `").append (w).append ("`='").append (v.to_string ()).append ("'"); return this; } public SelectStatement order (string order_by) { query_builder.append (" ORDER BY ").append (order_by); return this; } public SelectStatement limit (int limit) { query_builder.append (" LIMIT ").append (limit.to_string ()); return this; } public int run (SelectCallback callback) { Sqlite.Statement stmt; int ok = db.prepare_v2 (query_builder.str, -1, out stmt); if (ok != Sqlite.OK) { critical (db.errmsg ()); critical (query_builder.str); return 0; } bool next = true; int n_cols = stmt.column_count (); int n_rows = 0; while (stmt.step () == Sqlite.ROW && next) { string[] vals = new string[n_cols]; for (int i = 0; i < n_cols; i++) vals[i] = stmt.column_text (i); next = callback (vals); n_rows ++; } return n_rows; } public int64 once_i64 () { int64 back = -1; this.run ((vals) => { back = int64.parse (vals[0]); return false; }); return back; } } } corebird-1.1/src/sql/Statement.vala000066400000000000000000000062211260276623600173560ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace Sql { public interface IStatement { public abstract Sqlite.Database db { public set; protected get; } } public delegate bool SelectCallback (string[] vals); public class InsertStatement : IStatement { public unowned Sqlite.Database db { public set; private get; } private StringBuilder query_builder = new StringBuilder (); private Gee.ArrayList bindings = new Gee.ArrayList(); private bool ran = false; public InsertStatement (string table_name, bool replace = false) { if (replace) query_builder.append ("INSERT OR REPLACE INTO `"); else query_builder.append ("INSERT INTO `"); query_builder.append (table_name).append ("` ("); } public int64 run () { query_builder.append (") VALUES ("); query_builder.append ("?"); for (int i = 0; i < bindings.size -1; i++) query_builder.append (",?"); query_builder.append (");"); Sqlite.Statement stmt; int ok = db.prepare_v2 (query_builder.str, -1, out stmt); if (ok != Sqlite.OK) { critical (db.errmsg ()); return -1; } for (int i = 0; i < bindings.size; i++) { stmt.bind_text (i + 1, bindings.get (i)); } ok = stmt.step (); if (ok != Sqlite.DONE) { critical (db.errmsg ()); StringBuilder err_msg = new StringBuilder (); err_msg.append (stmt.sql ()).append (" --- "); for (int i = 0; i < bindings.size; i++) { err_msg.append (bindings.get (i)).append (", "); } critical (err_msg.str); } ran = true; return db.last_insert_rowid (); } public InsertStatement val (string col_name, string col_value) { if (bindings.size > 0) query_builder.append (", "); query_builder.append ("`").append (col_name).append ("`"); bindings.add (col_value); return this; } public InsertStatement vali (string col_name, int col_value) { return val (col_name, col_value.to_string ()); } public InsertStatement vali64 (string col_name, int64 col_value) { return val (col_name, col_value.to_string ()); } public InsertStatement valb (string col_name, bool col_value) { return val (col_name, col_value ? "1" : "0"); } #if DEBUG ~InsertStatement () { if (!ran) critical ("InsertStatement for %s did not run.", query_builder.str); } #endif } } corebird-1.1/src/sql/UpdateStatement.vala000066400000000000000000000056531260276623600205310ustar00rootroot00000000000000 /* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace Sql { public class UpdateStatement : IStatement { public unowned Sqlite.Database db { public set; private get; } private StringBuilder query_builder = new StringBuilder (); private Gee.ArrayList bindings = new Gee.ArrayList(); private bool ran = false; public UpdateStatement (string table_name) { query_builder.append ("UPDATE `").append (table_name).append ("` SET "); } public int64 run () { Sqlite.Statement stmt; query_builder.append(";"); int ok = db.prepare_v2 (query_builder.str, -1, out stmt); if (ok != Sqlite.OK) { critical (db.errmsg ()); return -1; } for (int i = 0; i < bindings.size; i++) { stmt.bind_text (i + 1, bindings.get (i)); } ok = stmt.step (); if (ok == Sqlite.ERROR) { critical (db.errmsg ()); critical (stmt.sql ()); return -1; } ran = true; return db.last_insert_rowid (); } public UpdateStatement where (string where) { query_builder.append (" WHERE ").append (where); return this; } public UpdateStatement where_eq (string col, string value) { query_builder.append (" WHERE `").append (col).append ("`='").append (value).append ("'"); return this; } public UpdateStatement where_eqi (string col, int64 iv) { return where_eq (col, iv.to_string ()); } public UpdateStatement val (string col_name, string col_value) { if (bindings.size > 0) query_builder.append (", "); query_builder.append ("`").append (col_name).append ("` = ?"); bindings.add (col_value); return this; } public UpdateStatement vali (string col_name, int col_value) { return val (col_name, col_value.to_string ()); } public UpdateStatement vali64 (string col_name, int64 col_value) { return val (col_name, col_value.to_string ()); } public UpdateStatement valb (string col_name, bool col_value) { return val (col_name, col_value ? "1" : "0"); } #if DEBUG ~UpdateStatement () { if (!ran) critical ("UpdateStatement for %s did not run.", query_builder.str); } #endif } } corebird-1.1/src/util/000077500000000000000000000000001260276623600147225ustar00rootroot00000000000000corebird-1.1/src/util/Benchmark.vala000066400000000000000000000006641260276623600174670ustar00rootroot00000000000000 namespace Benchmark { public class Bench { public string name; public GLib.DateTime first; public void stop () { var ts = new GLib.DateTime.now_local ().difference (first); int64 ms = (ts / 1000); message (@"$(this.name) took $ms ms"); } } public Bench start (string name) { var b = new Bench (); b.name = name; b.first = new GLib.DateTime.now_local (); return b; } } corebird-1.1/src/util/Bundle.vala000066400000000000000000000063221260276623600170030ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class Bundle : GLib.Object { private GLib.HashTable values; public uint size { get { return this.values.get_keys ().length (); } } public Bundle () { this.values = new GLib.HashTable (str_hash, str_equal); } public bool has_key (string key) { // O(n)... m( foreach (var k in values.get_keys ()) if (k == key) return true; return false; } public void put_string (string key, string value) { var v = GLib.Value (typeof (string)); v.set_string (value); values.insert (key, v); } public string? get_string (string key) { var v = this.values.get (key); if (v != null) return v.get_string (); return null; } public void put_int64 (string key, int64 value) { var v = GLib.Value (typeof (int64)); v.set_int64 (value); values.insert (key, v); } public int64 get_int64 (string key) { var v = this.values.get (key); if (v != null) return v.get_int64 (); return -1; } public void put_int (string key, int value) { var v = GLib.Value (typeof (int)); v.set_int (value); values.insert (key, v); } public int get_int (string key) { return values.get (key).get_int (); } public void put_object (string key, GLib.Object object) { var v = GLib.Value (typeof (GLib.Object)); v.set_object (object); values.insert (key, v); } public GLib.Object? get_object (string key) { return values.get (key).get_object (); } public void put_bool (string key, bool value) { var v = GLib.Value (typeof (bool)); v.set_boolean (value); values.insert (key, v); } public bool get_bool (string key, bool default) { var v = this.values.get (key); if (v != null) return v.get_boolean (); return default; } public GLib.Value? get_value (string key) { return this.values.get (key); } public string to_string () { var sb = new StringBuilder (); foreach (var key in values.get_keys ()) { sb.append ("%s -- %s".printf (key.to_string (), values.get (key).strdup_contents ())); } return sb.str; } public bool equals (Bundle? other) { if (other == null) return false; foreach (string key in this.values.get_keys ()) { if (!other.has_key (key)) return false; if (this.values.get (key).strdup_contents () != other.get_value (key).strdup_contents ()) return false; } return other.size == this.size; } } corebird-1.1/src/util/BundleHistory.vala000066400000000000000000000046421260276623600203700ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public class BundleHistory { private int[] elements; private Bundle[] bundles; private int pos = -1; public int current { get { if (pos == -1) return -1; return elements[pos]; } } public Bundle? current_bundle { get { if (pos == -1) return null; return bundles[pos]; } } public BundleHistory (int size) { elements = new int[size]; for (int i = 0; i < size; i++) elements[i] = -1; bundles = new Bundle[size]; } public void push (int v, Bundle? b) { if (pos < elements.length - 1) { pos ++; elements[pos] = v; bundles[pos] = b; } else { for (int i = 1; i < elements.length; i++) { elements[i-1] = elements[i]; bundles[i-1] = bundles[i]; } elements[pos] = v; bundles[pos] = b; } } public int back () { if (pos > 0) { pos--; return elements[pos]; } return -1; } public int forward () { if (pos < elements.length - 1) { pos ++; return elements[pos]; } return -1; } public bool at_start () { return pos == 0; } public bool at_end () { if (pos == elements.length -1) return true; if (elements[pos] == -1 || elements[pos + 1] == -1) return true; return false; } public string to_string () { string a = "["; for (int i = 0; i < elements.length; i++) { string bundle_str = bundles[i] != null ? bundles[i].to_string () : ""; if (i == pos) a += "*"+elements[i].to_string ()+"*(" + bundle_str + "),"; else a += elements[i].to_string ()+"(" + bundle_str + "),"; } a += "]"; return a; } } corebird-1.1/src/util/Config.vala.in000066400000000000000000000016361260276623600174070ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public const string DATADIR = "@prefix@/share/corebird/"; public const string LOCALEDIR = "@prefix@/share/locale"; public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"; corebird-1.1/src/util/Dirs.vala000066400000000000000000000044361260276623600164770ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace Dirs { static string? config_dir = null; static string? cache_dir = null; static string? data_dir = null; public void create_dirs () { create_folder (cache ("")); create_folder (cache ("assets")); create_folder (cache ("assets/banners/")); create_folder (cache ("assets/media/")); create_folder (cache ("assets/media/thumbs/")); create_folder (config ("")); create_folder (config ("accounts/")); create_folder (data ("")); create_folder (data ("logs/")); } public string cache (string path) { if (cache_dir == null) { cache_dir = GLib.Environment.get_user_cache_dir () + "/corebird/"; } return cache_dir + path; } string data (string path) { if (data_dir == null) { data_dir = GLib.Environment.get_user_data_dir () + "/corebird/"; } return data_dir + path; } public string config (string path) { if (config_dir == null) { config_dir = GLib.Environment.get_home_dir () + "/.corebird/"; if (!GLib.FileUtils.test (config_dir, GLib.FileTest.EXISTS)) { config_dir = GLib.Environment.get_user_config_dir () + "/corebird/"; } } return config_dir + path; } private void create_folder (string path) { if (FileUtils.test (path, FileTest.EXISTS)) return; try { bool success = File.new_for_path (path) .make_directory (); if (!success) { critical("Couldn't create user folder %s", path); } } catch (GLib.Error e) { critical ("%s(%s)", e.message, path); } } } corebird-1.1/src/util/TextTransform.vala000066400000000000000000000135061260276623600204140ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ public struct TextEntity { uint from; uint to; string display_text; string tooltip_text; string? target; // If target is null, use display_text as target! uint info; } //void print_e (TextEntity ent) { //message ("Entity (range = %u..%u, display_text = '%s', target = '%s'", //ent.from, ent.to, ent.display_text, ent.target); //} public enum TransformFlags { REMOVE_MEDIA_LINKS = 1 << 0, REMOVE_TRAILING_HASHTAGS = 1 << 1, EXPAND_LINKS = 1 << 2 } namespace TextTransform { private static const uint TRAILING = 1 << 0; private bool is_media_url (string? url, string display_text, uint media_count) { return (is_media_candidate (url ?? display_text) && media_count == 1) || display_text.has_prefix ("pic.twitter.com/"); } private bool is_hashtag (string entity) { return entity[0] == '#'; } private bool is_link (string? target) { return target != null && (target.has_prefix ("http://") || target.has_prefix ("https://")); } private bool is_quote_link (ref TextEntity entity, int64 quote_id) { if (entity.target == null) return false; return (entity.target.has_prefix ("https://twitter.com/") && entity.target.has_suffix ("/status/" + quote_id.to_string ())); } private bool is_whitespace (string s) { unichar c; for (int i = 0; s.get_next_char (ref i, out c);) { if (c.isgraph ()) return false; } return true; } public string transform_tweet (MiniTweet tweet, TransformFlags flags, int64 quote_id = -1) { return transform (tweet.text, tweet.entities, flags, tweet.medias.length, quote_id); } // XXX We could probably do this a bit faster and simpler (and in one step!) // if we just built the new string from end to start. public string transform (string text, TextEntity[] entities, TransformFlags flags, uint media_count = 0, int64 quote_id = -1) { StringBuilder builder = new StringBuilder (); uint last_end = 0; uint cur_end = text.char_count (); for (int i = entities.length - 1; i >= 0; i --) { /* Check that only whitespace is between the two entities */ string btw = text.substring (text.index_of_nth_char (entities[i].to), text.index_of_nth_char (cur_end) - text.index_of_nth_char (entities[i].to)); if (!is_whitespace (btw) && btw.length > 0) { break; } else cur_end = entities[i].to; if (entities[i].to == cur_end && (is_hashtag (entities[i].display_text) || is_link (entities[i].target))) { entities[i].info |= TRAILING; cur_end = entities[i].from; } else break; } bool last_entity_was_trailing = false; foreach (TextEntity entity in entities) { /* Append part before this entity */ string before = text.substring (text.index_of_nth_char (last_end), text.index_of_nth_char (entity.from) - text.index_of_nth_char (last_end)); if (!(last_entity_was_trailing && is_whitespace (before))) builder.append (before); if (TransformFlags.REMOVE_TRAILING_HASHTAGS in flags && (entity.info & TRAILING) > 0 && is_hashtag (entity.display_text)) { last_end = entity.to; last_entity_was_trailing = true; continue; } last_entity_was_trailing = false; /* Skip the entire entity if we should remove media links AND it is a media link. */ if ((TransformFlags.REMOVE_MEDIA_LINKS in flags && is_media_url (entity.target, entity.display_text, media_count)) || (quote_id != 0 && is_quote_link (ref entity, quote_id))) { last_end = entity.to; continue; } if (TransformFlags.EXPAND_LINKS in flags) { if (entity.display_text[0] == '@') builder.append (entity.display_text); else builder.append (entity.target ?? entity.display_text); } else { /* Append start of link + entity target */ builder.append (""); builder.append (entity.display_text.replace ("&", "&")); builder.append (""); } last_end = entity.to; } /* Append last part of the source string */ builder.append (text.substring (text.index_of_nth_char (last_end))); /* Replace all & with & */ return builder.str; } } corebird-1.1/src/util/TweetUtils.vala000066400000000000000000000365431260276623600177130ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ namespace TweetUtils { private static const string[] DOMAINS = { ".com", ".net", ".org", ".xxx", ".sexy", ".pro", ".biz", ".name", ".info", ".arpa", ".gov", ".aero", ".asia", ".cat", ".coop", ".edu", ".int", ".jobs", ".mil", ".mobi", ".museum", ".post", ".tel", ".travel" }; /** * Deletes the given tweet. * * @param account The account to delete the tweet from * @param tweet the tweet to delete */ async void delete_tweet (Account account, Tweet tweet) { var call = account.proxy.new_call (); call.set_method ("POST"); call.set_function ("1.1/statuses/destroy/"+tweet.id.to_string ()+".json"); call.add_param ("id", tweet.id.to_string ()); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res);} catch (GLib.Error e) { critical (e.message);} delete_tweet.callback (); }); yield; } /** * Replies to the given tweet. This intended for quick/easy replies, without any * additional data such as media. * * @param account The account to reply from * @param tweet The tweet to reply to * @param text The text to reply */ async void reply_to_tweet (Account account, Tweet tweet, string text) { var call = account.proxy.new_call (); call.set_function ("1.1/statuses/update.json"); call.set_method ("POST"); call.add_param ("in_reply_to_status_id", tweet.id.to_string ()); call.add_param ("status", text); call.invoke_async.begin (null, () => { reply_to_tweet.callback (); }); yield; } /** * (Un)favorites the given tweet. * * @param account The account to (un)favorite from * @param tweet The tweet to (un)favorite * @param unfavorite If set to true, this function will unfavorite the tiven tweet, * else it will favorite it. */ async void toggle_favorite_tweet (Account account, Tweet tweet, bool unfavorite = false) { var call = account.proxy.new_call(); if (!unfavorite) call.set_function ("1.1/favorites/create.json"); else call.set_function ("1.1/favorites/destroy.json"); call.set_method ("POST"); call.add_param ("id", tweet.id.to_string ()); call.invoke_async.begin (null, (obj, res) => { try { call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } tweet.favorited = !unfavorite; toggle_favorite_tweet.callback (); }); yield; } /** * (Un)retweets the given tweet. * * @param account The account to (un)retweet from * @param tweet The tweet to (un)retweet * @param unretweet If set to true, this function will delete te retweet of #tweet, * else it will retweet it. */ async void toggle_retweet_tweet (Account account, Tweet tweet, bool unretweet = false) { var call = account.proxy.new_call (); call.set_method ("POST"); if (!unretweet) call.set_function (@"1.1/statuses/retweet/$(tweet.id).json"); else call.set_function (@"1.1/statuses/destroy/$(tweet.my_retweet).json"); call.invoke_async.begin (null, (obj, res) => { try{ call.invoke_async.end (res); } catch (GLib.Error e) { Utils.show_error_object (call.get_payload (), e.message, GLib.Log.LINE, GLib.Log.FILE); } string back = call.get_payload(); var parser = new Json.Parser (); try { parser.load_from_data (back); if (!unretweet) { int64 new_id = parser.get_root ().get_object ().get_int_member ("id"); tweet.my_retweet = new_id; } else { tweet.my_retweet = 0; } tweet.retweeted = !unretweet; } catch (GLib.Error e) { critical (e.message); critical (back); } toggle_retweet_tweet.callback (); }); yield; } /** * Downloads the avatar from the given url. * * @param avatar_url The avatar url to download * * @return The loaded avatar. */ async Gdk.Pixbuf download_avatar (string avatar_url, int size = 48) throws GLib.Error { Gdk.Pixbuf avatar = null; var msg = new Soup.Message ("GET", avatar_url); GLib.Error? err = null; SOUP_SESSION.queue_message (msg, (s, _msg) => { var memory_stream = new MemoryInputStream.from_data(_msg.response_body.data, null); try { avatar = new Gdk.Pixbuf.from_stream_at_scale (memory_stream, size, size, false); } catch (GLib.Error e) { err = e; } download_avatar.callback (); }); yield; if (err != null) { throw err; } return avatar; } /** * Calculates the length of a tweet. * See https://dev.twitter.com/docs/faq#5810 for details * * @param text The text to calculate the length for * * @return The length of the tweet, taking Twitter's rules for * tweet length into account. */ public int calc_tweet_length (string text, int media_count = 0) { string[] words = text.split (" "); int length = 0; foreach (string s in words) { string[] subwords = s.split ("\n"); foreach (string sw in subwords) { length += get_word_length (sw); } length += subwords.length - 1; } // Don't forget the n-1 whitespaces length += words.length - 1; if (length < 0) { return Twitter.short_url_length_https * media_count; } length += Twitter.short_url_length_https * media_count; return length; } private int get_word_length (string s) { if (s.has_prefix ("www.") || s.has_prefix ("http://")) return Twitter.short_url_length; if (s.has_prefix ("https://")) return Twitter.short_url_length_https; foreach (string tld in DOMAINS) { string[] parts = s.split ("/"); if (parts.length > 0 && parts[0].has_suffix (tld)) return Twitter.short_url_length; // Default to HTTP } return s.char_count(); } bool activate_link (string uri, MainWindow window) { uri = uri._strip (); string term = uri.substring (1); if (uri.has_prefix ("@")) { int slash_index = uri.index_of ("/"); var bundle = new Bundle (); if (slash_index == -1) { bundle.put_int64 ("user_id", int64.parse (term)); window.main_widget.switch_page (Page.PROFILE, bundle); } else { bundle.put_int64 ("user_id", int64.parse (term.substring (0, slash_index - 1))); bundle.put_string ("screen_name", term.substring (slash_index + 1, term.length - slash_index - 1)); window.main_widget.switch_page (Page.PROFILE, bundle); } return true; } else if (uri.has_prefix ("#")) { var bundle = new Bundle (); bundle.put_string ("query", uri); window.main_widget.switch_page (Page.SEARCH, bundle); return true; } else if (uri.has_prefix ("https://twitter.com/")) { // https://twitter.com/baedert/status/321423423423 string[] parts = uri.split ("/"); if (parts[4] == "status") { /* Treat it as a tweet link and hope it'll work out */ int64 tweet_id = int64.parse (parts[5]); var bundle = new Bundle (); bundle.put_int ("mode", TweetInfoPage.BY_ID); bundle.put_int64 ("tweet_id", tweet_id); bundle.put_string ("screen_name", parts[3]); window.main_widget.switch_page (Page.TWEET_INFO, bundle); return true; } } return false; } async void work_array (Json.Array json_array, TweetListBox tweet_list, MainWindow main_window, Account account) { new Thread ("TweetWorker", () => { Tweet[] tweet_array = new Tweet[json_array.get_length ()]; /* If the request returned no results at all, we don't need to do all the later stuff */ if (tweet_array.length == 0) { GLib.Idle.add (() => { work_array.callback (); return false; }); return null; } var now = new GLib.DateTime.now_local (); json_array.foreach_element ((array, index, node) => { Tweet t = new Tweet (); t.load_from_json (node, now, account); tweet_array[index] = t; }); int index = 0; GLib.Idle.add (() => { Tweet tweet = tweet_array[index]; if (account.user_counter == null) return false; account.user_counter.id_seen (ref tweet.source_tweet.author); if (tweet.retweeted_tweet != null) account.user_counter.id_seen (ref tweet.retweeted_tweet.author); if (account.filter_matches (tweet)) tweet.hidden_flags |= Tweet.HIDDEN_FILTERED; tweet_list.model.add (tweet); index ++; if (index == tweet_array.length) { work_array.callback (); return false; } return true; }); return null; }); yield; } public void handle_media_click (Tweet t, MainWindow window, int index) { MediaDialog media_dialog = new MediaDialog (t, index); media_dialog.set_transient_for (window); media_dialog.set_modal (true); media_dialog.show (); } public bool is_link (string word) { if (word.has_prefix ("http://") && word.length > 7) return true; if (word.has_prefix ("https://") && word.length > 8) return true; foreach (string tld in DOMAINS) if (word.has_suffix (tld)) return true; return false; } private const unichar[] non_mention_chars = { '“', '"', '-', '`', ',', '.', '^', '(', ')', '[', ']', '{', '}', '+', '=' }; public bool is_mention (string word, out int at_pos) { int k = 0; while (word.get_char (k) in non_mention_chars) k ++; at_pos = k; return word.get_char (word.index_of_nth_char (k)) == '@' && word.length > 1 && word.length - k > 1; } public bool is_hashtag (string word) { return word[0] == '#' && word.length > 1; } private void highlight_link (Gtk.TextBuffer buffer, Gtk.TextIter? word_start, Gtk.TextIter? word_end) { Gtk.TextIter? iter1 = word_start; Gtk.TextIter? iter2 = word_start; iter1.forward_char (); iter2.forward_chars (2); while (iter1.compare (word_end) < 0) { string t = buffer.get_text (iter1, iter2, false); unichar c = t.get_char (0); if (c == '"' || c == '“') { break; } iter1.forward_char (); iter2.forward_char (); } buffer.apply_tag_by_name ("link", word_start, iter1); } /** Invariant: The word passed to this function starts with a @ */ private void highlight_mention (Gtk.TextBuffer buffer, Gtk.TextIter? word_start, Gtk.TextIter? word_end) { Gtk.TextIter? iter1 = word_start; Gtk.TextIter? iter2 = word_start; iter1.forward_char (); iter2.forward_chars (2); while (iter1.compare (word_end) < 0) { string t = buffer.get_text (iter1, iter2, false); unichar c = t.get_char (0); if ((c.ispunct () && c != '_') || c == '"' || c == '“') { break; } iter1.forward_char (); iter2.forward_char (); } buffer.apply_tag_by_name ("mention", word_start, iter1); } /** Invariant: the word passed to this function starts with a # */ private void highlight_hashtag (Gtk.TextBuffer buffer, Gtk.TextIter? word_start, Gtk.TextIter? word_end) { Gtk.TextIter? iter1 = word_start; Gtk.TextIter? iter2 = word_start; iter1.forward_char (); iter2.forward_chars (2); while (iter1.compare (word_end) < 0) { string t = buffer.get_text (iter1, iter2, false); unichar c = t.get_char (0); if ((c.ispunct () && c != '_') || c == '”') { break; } iter1.forward_char (); iter2.forward_char (); } buffer.apply_tag_by_name ("hashtag", word_start, iter1); } public void annotate_text (Gtk.TextBuffer buffer) { Gtk.TextIter? start_iter; Gtk.TextIter? cur_iter; Gtk.TextIter? word_start_iter; Gtk.TextIter? next_iter; buffer.get_start_iter (out start_iter); cur_iter = start_iter; word_start_iter = cur_iter; while (true) { /* If we are at a space, we just drag the start_iter with us */ if (cur_iter.get_char ().isspace()) { word_start_iter = cur_iter; word_start_iter.forward_char (); } next_iter = cur_iter; bool done = !next_iter.forward_char (); bool word_end = done || (next_iter.get_char ().isspace() && !cur_iter.get_char ().isspace()); if (word_end) { // We are at the end of a word so highlight it accordingly int k; string w = buffer.get_text (word_start_iter, next_iter, false); if (is_link (w)) { highlight_link (buffer, word_start_iter, next_iter); } else if (is_mention (w, out k)) { word_start_iter.forward_chars (k); highlight_mention (buffer, word_start_iter, next_iter); } else if (is_hashtag (w)) { highlight_hashtag (buffer, word_start_iter, next_iter); } } if (done) break; cur_iter = next_iter; } } public async Json.Node? load_threaded (Rest.ProxyCall call) throws GLib.Error { Json.Node? result = null; GLib.Error? err = null; GLib.SourceFunc callback = load_threaded.callback; new Thread ("json parser", () => { try { call.sync (); } catch (GLib.Error e) { err = e; return null; } var parser = new Json.Parser (); try { parser.load_from_data (call.get_payload ()); } catch (GLib.Error e) { err = e; return null; } result = parser.get_root (); GLib.Idle.add (() => { callback (); return GLib.Source.REMOVE; }); return null; }); yield; if (err != null) throw err; return result; } public void sort_entities (ref TextEntity[] entities) { /* Just use bubblesort here. Our n is very small (< 15 maybe?) */ for (int i = 0; i < entities.length; i ++) { for (int k = 0; k < entities.length; k ++) { if (entities[i].from < entities[k].from) { TextEntity c = entities[i]; entities[i] = entities[k]; entities[k] = c; } } } } } corebird-1.1/src/util/UserCompletion.vala000066400000000000000000000033641260276623600205450ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ class UserCompletion : GLib.Object { public signal void start_completion (); public signal void populate_completion (string name, string screen_name); private unowned GLib.Object obj; private unowned Account account; private string name_property_name; private int num_results; public UserCompletion (Account account, int num_results) { this.account = account; this.num_results = num_results; } public void connect_to (GLib.Object obj, string name_property_name) { this.obj = obj; this.name_property_name = name_property_name; obj.notify[name_property_name].connect (prop_changed); } private void prop_changed () { string name; obj.get (name_property_name, out name); if (name.has_prefix ("@")) name = name.substring (1); start_completion (); int n_results; UserInfo[] names = account.user_counter.query_by_prefix (name, 10, out n_results); for (int i = 0; i < n_results; i++) populate_completion (names[i].screen_name, names[i].name); } } corebird-1.1/src/util/UserUtils.vala000066400000000000000000000103641260276623600175320ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ struct Friendship { bool followed_by; bool following; bool want_retweets; bool blocking; } struct Cursor { int64 next_cursor; bool full; Json.Node? json_object; } namespace UserUtils { async Friendship? load_friendship (Account account, int64 user_id) { var call = account.proxy.new_call (); call.set_function ("1.1/friendships/show.json"); call.set_method ("GET"); call.add_param ("source_id", account.id.to_string ()); call.add_param ("target_id", user_id.to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return null; } var relationship = root.get_object ().get_object_member ("relationship"); var target = relationship.get_object_member ("target"); var source = relationship.get_object_member ("source"); var friendship = Friendship (); friendship.followed_by = target.get_boolean_member ("following"); friendship.following = target.get_boolean_member ("followed_by"); friendship.want_retweets = source.get_boolean_member ("want_retweets"); friendship.blocking = source.get_boolean_member ("blocking"); // XXX This gets copied and I just want to rewrite this in C. return friendship; } async Cursor? load_followers (Account account, int64 user_id, Cursor? old_cursor) { const int requested = 25; var call = account.proxy.new_call (); call.set_function ("1.1/followers/list.json"); call.set_method ("GET"); call.add_param ("user_id", user_id.to_string ()); call.add_param ("count", requested.to_string ()); call.add_param ("skip_status", "true"); call.add_param ("include_user_entities", "false"); if (old_cursor != null) call.add_param ("cursor", old_cursor.next_cursor.to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return null; } var root_obj = root.get_object (); var user_array = root_obj.get_array_member ("users"); Cursor cursor = Cursor (); cursor.next_cursor = root_obj.get_int_member ("next_cursor"); cursor.full = (user_array.get_length () < requested); cursor.json_object = root_obj.get_member ("users"); return cursor; } async Cursor? load_following (Account account, int64 user_id, Cursor? old_cursor) { const int requested = 25; var call = account.proxy.new_call (); call.set_function ("1.1/friends/list.json"); call.set_method ("GET"); call.add_param ("user_id", user_id.to_string ()); call.add_param ("count", requested.to_string ()); call.add_param ("skip_status", "true"); call.add_param ("include_user_entities", "false"); if (old_cursor != null) call.add_param ("cursor", old_cursor.next_cursor.to_string ()); Json.Node? root = null; try { root = yield TweetUtils.load_threaded (call); } catch (GLib.Error e) { warning (e.message); return null; } var root_obj = root.get_object (); var user_array = root_obj.get_array_member ("users"); Cursor cursor = Cursor (); cursor.next_cursor = root_obj.get_int_member ("next_cursor"); cursor.full = (user_array.get_length () < requested); cursor.json_object = root_obj.get_member ("users"); return cursor; } } corebird-1.1/src/util/Utils.vala000066400000000000000000000356561260276623600167060ustar00rootroot00000000000000/* This file is part of corebird, a Gtk+ linux Twitter client. * Copyright (C) 2013 Timm Bäder * * corebird is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * corebird is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with corebird. If not, see . */ enum Page { STREAM = 0, MENTIONS, FAVORITES, DM_THREADS, LISTS, FILTERS, SEARCH, PROFILE, TWEET_INFO, DM, LIST_STATUSES, PREVIOUS = 1024, NEXT = 2048 } static Soup.Session SOUP_SESSION = null; void default_header_func (Gtk.ListBoxRow row, Gtk.ListBoxRow? row_before) { if (row_before == null) { row.set_header (null); return; } Gtk.Widget? header = row.get_header (); if (header != null) { return; } header = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); header.show (); row.set_header (header); } Cairo.Surface? load_surface (string path) { try { var p = new Gdk.Pixbuf.from_file (path); var s = Gdk.cairo_surface_create_from_pixbuf (p, 1, null); return s; } catch (GLib.Error e) { warning (e.message); return null; } } void write_surface (Cairo.Surface surface, string path) { var status = surface.write_to_png (path); if (status != Cairo.Status.SUCCESS) { warning ("Could not write surface to '%s': %s", path, status.to_string ()); } } Cairo.Surface scale_surface (Cairo.ImageSurface input, int output_width, int output_height) { Cairo.Surface new_surface = new Cairo.Surface.similar_image (input, Cairo.Format.ARGB32, output_width, output_height); int old_width = input.get_width (); int old_height = input.get_height (); /* http://lists.cairographics.org/archives/cairo/2006-January/006178.html */ Cairo.Context ct = new Cairo.Context (new_surface); ct.scale ((double)output_width / old_width, (double)output_height / old_height); ct.set_source_surface (input, 0, 0); ct.get_source ().set_extend (Cairo.Extend.PAD); ct.set_operator (Cairo.Operator.SOURCE); ct.paint (); return new_surface; } namespace Utils { /** * Parses a date given by Twitter in the form 'Wed Jun 20 19:01:28 +0000 2012' * and creates a GLib.DateTime in the local time zone to work with. * * @return The given date as GLib.DateTime in the current time zone. */ GLib.DateTime parse_date (string input) { if (input == "") { return new GLib.DateTime.now_local (); } string month_str = input.substring (4, 3); int day = int.parse (input.substring (8, 2)); int year = int.parse (input.substring (input.length - 4)); string timezone = input.substring (20, 5); int month = -1; switch (month_str) { case "Jan": month = 1; break; case "Feb": month = 2; break; case "Mar": month = 3; break; case "Apr": month = 4; break; case "May": month = 5; break; case "Jun": month = 6; break; case "Jul": month = 7; break; case "Aug": month = 8; break; case "Sep": month = 9; break; case "Oct": month = 10; break; case "Nov": month = 11; break; case "Dec": month = 12; break; } int hour = int.parse (input.substring (11, 2)); int minute = int.parse (input.substring (14, 2)); int second = int.parse (input.substring (17, 2)); GLib.DateTime dt = new GLib.DateTime (new GLib.TimeZone(timezone), year, month, day, hour, minute, second); return dt.to_timezone (new TimeZone.local ()); } /** * Calculates an easily human-readable version of the time difference between * time and now. * Example: "5m" or "3h" or "26m" or "16 Nov" */ public string get_time_delta (GLib.DateTime time, GLib.DateTime now) { //diff is the time difference in microseconds GLib.TimeSpan diff = now.difference (time); int minutes = (int)(diff / 1000.0 / 1000.0 / 60.0); if (minutes == 0) return _("Now"); else if (minutes < 60) return _("%dm").printf (minutes); int hours = (int)(minutes / 60.0); if (hours < 24) return _("%dh").printf (hours); string month = time.format ("%b"); //If 'time' was over 24 hours ago, we just return that return "%d %s".printf (time.get_day_of_month (), month); } /** * Extracts the actual filename out of a given path. * E.g. for /home/foo/bar.png, it will return "bar.png" * * @return The filename of the given path, and nothing else. */ string get_file_name (string path) { return path.substring (path.last_index_of_char ('/') + 1); } /** * Extracts the file type from the given path. * E.g. for http://foo.org/bar/bla.png, this will just return "png" */ public string get_file_type (string path) { string filename = get_file_name (path); if (filename.index_of_char ('.') == -1) return ""; string type = filename.substring (filename.last_index_of_char ('.') + 1); type = type.down (); if (type == "jpg") return "jpeg"; return type; } /** * Returns the avatar name for the given path * * @return the 'calculated' avatar name */ string get_avatar_name (string path) { string[] parts = path.split ("/"); return parts[parts.length - 2] + "_" + parts[parts.length - 1]; } /** * Shows an error dialog with the given error message * * @param message The error message to show */ void show_error_dialog (string message) { var dialog = new Gtk.MessageDialog (null, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "%s", message); dialog.response.connect((id) => { if(id == Gtk.ResponseType.OK) dialog.destroy(); }); dialog.show(); } /** * Shows the given json error object in an error dialog. * Example object data: * {"errors":[{"message":"Could not authenticate you","code":32}] * * @param json_data The json data to show * @param alternative If the given json data is not valid, * show this alternative error message. */ void show_error_object (string? json_data, string alternative, int line, string file) { string error_message = "Exception: %s in %s:%d".printf (alternative, file, line); if (json_data == null) { show_error_dialog (error_message); return; } var parser = new Json.Parser (); StringBuilder sb = new StringBuilder (); try { parser.load_from_data (json_data); } catch (GLib.Error e) { show_error_dialog (error_message); return; } if (parser.get_root ().get_node_type () != Json.NodeType.OBJECT) { show_error_dialog (error_message); return; } var root = parser.get_root ().get_object (); if (root.has_member ("error") && root.get_member ("error").get_node_type () == Json.NodeType.VALUE) { message (json_data); show_error_dialog (root.get_member ("error").get_string ()); return; } if (root.get_member ("errors").get_node_type () == Json.NodeType.VALUE) { message (json_data); show_error_dialog (root.get_member ("errors").get_string ()); return; } var errors = root.get_array_member ("errors"); if (errors.get_length () == 1) { var err = errors.get_object_element (0); sb.append (err.get_int_member ("code").to_string ()).append (": ") .append (err.get_string_member ("message")) .append ("(").append (file).append (":").append (line.to_string ()).append (")"); } else { sb.append ("