phcteam team mailing list archive
-
phcteam team
-
Mailing list archive
-
Message #00148
[Merge] lp:~r2d2.art2005/slidewall/slidewall into lp:slidewall
fioan89@xxxxxxxxx has proposed merging lp:~r2d2.art2005/slidewall/slidewall into lp:slidewall.
Requested reviews:
PHC Team (phcteam)
Related bugs:
Bug #1035770 in Slidewall: "clock.ini is ignored when choosing hourXX.png"
https://bugs.launchpad.net/slidewall/+bug/1035770
For more details, see:
https://code.launchpad.net/~r2d2.art2005/slidewall/slidewall/+merge/163233
--
https://code.launchpad.net/~r2d2.art2005/slidewall/slidewall/+merge/163233
Your team PHC Team is requested to review the proposed merge of lp:~r2d2.art2005/slidewall/slidewall into lp:slidewall.
=== added file '.quickly'
--- .quickly 1970-01-01 00:00:00 +0000
+++ .quickly 2013-05-09 22:05:30 +0000
@@ -0,0 +1,5 @@
+project = slidewall
+version = 12.04
+template = ubuntu-application
+lp_id = slidewall
+ppa = slidewall
=== added file 'AUTHORS'
--- AUTHORS 1970-01-01 00:00:00 +0000
+++ AUTHORS 2013-05-09 22:05:30 +0000
@@ -0,0 +1,1 @@
+Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
=== added file 'COPYING'
--- COPYING 1970-01-01 00:00:00 +0000
+++ COPYING 2013-05-09 22:05:30 +0000
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+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:
+
+ <program> Copyright (C) <year> <name of author>
+ 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
+<http://www.gnu.org/licenses/>.
+
+ 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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
=== added file 'TODO'
--- TODO 1970-01-01 00:00:00 +0000
+++ TODO 2013-05-09 22:05:30 +0000
@@ -0,0 +1,15 @@
+[]try to improve Live mode ->wallbase features
+[x]find new features for Live mode
+[x]force slidewall to automatically save the setting without using
+the save button
+[x]add option to start Slidewall when Ubuntu start
+[x]integrate Slidewall with system tray
+[]integrate Slidewall with Unity System Settings
+[x]Add vladstudio clock support
+[]Add option to import new vladstudio clocks
+[]Add option to delete vladstudio clock's but don't let the user to delete
+the default clock's or any other widget's from LiveMode
+[x]There are some problems with different clocks that don't show your hour.
+[]refresh hour for vladstudio clock less
+
+
=== added directory 'bin'
=== added file 'bin/slidewall'
--- bin/slidewall 1970-01-01 00:00:00 +0000
+++ bin/slidewall 2013-05-09 22:05:30 +0000
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import sys
+import os
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+# Add project root directory (enable symlink and trunk execution)
+PROJECT_ROOT_DIRECTORY = os.path.abspath(
+ os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0]))))
+
+python_path = []
+if os.path.abspath(__file__).startswith('/opt'):
+ syspath = sys.path[:] # copy to avoid infinite loop in pending objects
+ for path in syspath:
+ opt_path = path.replace('/usr', '/opt/extras.ubuntu.com/slidewall')
+ python_path.insert(0, opt_path)
+ sys.path.insert(0, opt_path)
+if (os.path.exists(os.path.join(PROJECT_ROOT_DIRECTORY, 'slidewall'))
+ and PROJECT_ROOT_DIRECTORY not in sys.path):
+ python_path.insert(0, PROJECT_ROOT_DIRECTORY)
+ sys.path.insert(0, PROJECT_ROOT_DIRECTORY)
+if python_path:
+ os.putenv('PYTHONPATH', "%s:%s" % (os.getenv('PYTHONPATH', ''), ':'.join(python_path))) # for subprocesses
+
+import slidewall
+slidewall.main()
=== added directory 'data'
=== added directory 'data/glib-2.0'
=== added directory 'data/glib-2.0/schemas'
=== added file 'data/glib-2.0/schemas/gschemas.compiled'
Binary files data/glib-2.0/schemas/gschemas.compiled 1970-01-01 00:00:00 +0000 and data/glib-2.0/schemas/gschemas.compiled 2013-05-09 22:05:30 +0000 differ
=== added file 'data/glib-2.0/schemas/net.launchpad.slidewall.gschema.xml'
--- data/glib-2.0/schemas/net.launchpad.slidewall.gschema.xml 1970-01-01 00:00:00 +0000
+++ data/glib-2.0/schemas/net.launchpad.slidewall.gschema.xml 2013-05-09 22:05:30 +0000
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist gettext-domain="slidewall">
+ <schema id="net.launchpad.slidewall" path="/net/launchpad/slidewall/">
+ <key name="example" type="s">
+ <default>''</default>
+ <summary>Sample setting</summary>
+ <description>Longer description of this sample setting. Talk about allowed values and what it does.</description>
+ </key>
+ </schema>
+</schemalist>
=== added directory 'data/media'
=== added file 'data/media/background.png'
Binary files data/media/background.png 1970-01-01 00:00:00 +0000 and data/media/background.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/media/goldflame'
=== added file 'data/media/goldflame/am.png'
Binary files data/media/goldflame/am.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/am.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/bg.jpg'
Binary files data/media/goldflame/bg.jpg 1970-01-01 00:00:00 +0000 and data/media/goldflame/bg.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/clock.ini'
--- data/media/goldflame/clock.ini 1970-01-01 00:00:00 +0000
+++ data/media/goldflame/clock.ini 2013-05-09 22:05:30 +0000
@@ -0,0 +1,15 @@
+[Settings]
+name=Gold Flame
width=1440
+height=900
author=Vlad Gerasimov
email=vladstudio@xxxxxxxxx
ampmenabled=1
+description=
+homepageURL=http://www.vladstudio.com
+downloadURL=http://www.vladstudio.powweb.com/wcz/goldflame.wcz
+refreshhourinterval=60
+hourimages=24
+
+[Animation]
+
+[WallpaperClock]
+specVersion=1.0
+specampmenabled=1
+description=http://www.wallpaperclock.com/wcz/spec.php
\ No newline at end of file
=== added file 'data/media/goldflame/day1.png'
Binary files data/media/goldflame/day1.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day10.png'
Binary files data/media/goldflame/day10.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day11.png'
Binary files data/media/goldflame/day11.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day12.png'
Binary files data/media/goldflame/day12.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day13.png'
Binary files data/media/goldflame/day13.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day14.png'
Binary files data/media/goldflame/day14.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day15.png'
Binary files data/media/goldflame/day15.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day16.png'
Binary files data/media/goldflame/day16.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day17.png'
Binary files data/media/goldflame/day17.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day18.png'
Binary files data/media/goldflame/day18.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day19.png'
Binary files data/media/goldflame/day19.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day2.png'
Binary files data/media/goldflame/day2.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day20.png'
Binary files data/media/goldflame/day20.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day21.png'
Binary files data/media/goldflame/day21.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day22.png'
Binary files data/media/goldflame/day22.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day23.png'
Binary files data/media/goldflame/day23.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day24.png'
Binary files data/media/goldflame/day24.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day25.png'
Binary files data/media/goldflame/day25.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day26.png'
Binary files data/media/goldflame/day26.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day27.png'
Binary files data/media/goldflame/day27.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day28.png'
Binary files data/media/goldflame/day28.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day29.png'
Binary files data/media/goldflame/day29.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day3.png'
Binary files data/media/goldflame/day3.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day30.png'
Binary files data/media/goldflame/day30.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day31.png'
Binary files data/media/goldflame/day31.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day4.png'
Binary files data/media/goldflame/day4.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day5.png'
Binary files data/media/goldflame/day5.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day6.png'
Binary files data/media/goldflame/day6.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day7.png'
Binary files data/media/goldflame/day7.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day8.png'
Binary files data/media/goldflame/day8.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/day9.png'
Binary files data/media/goldflame/day9.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/day9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour0.png'
Binary files data/media/goldflame/hour0.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour1.png'
Binary files data/media/goldflame/hour1.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour10.png'
Binary files data/media/goldflame/hour10.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour11.png'
Binary files data/media/goldflame/hour11.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour12.png'
Binary files data/media/goldflame/hour12.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour13.png'
Binary files data/media/goldflame/hour13.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour14.png'
Binary files data/media/goldflame/hour14.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour15.png'
Binary files data/media/goldflame/hour15.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour16.png'
Binary files data/media/goldflame/hour16.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour17.png'
Binary files data/media/goldflame/hour17.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour18.png'
Binary files data/media/goldflame/hour18.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour19.png'
Binary files data/media/goldflame/hour19.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour2.png'
Binary files data/media/goldflame/hour2.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour20.png'
Binary files data/media/goldflame/hour20.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour21.png'
Binary files data/media/goldflame/hour21.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour22.png'
Binary files data/media/goldflame/hour22.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour23.png'
Binary files data/media/goldflame/hour23.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour3.png'
Binary files data/media/goldflame/hour3.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour4.png'
Binary files data/media/goldflame/hour4.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour5.png'
Binary files data/media/goldflame/hour5.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour6.png'
Binary files data/media/goldflame/hour6.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour7.png'
Binary files data/media/goldflame/hour7.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour8.png'
Binary files data/media/goldflame/hour8.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/hour9.png'
Binary files data/media/goldflame/hour9.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/hour9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute0.png'
Binary files data/media/goldflame/minute0.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute1.png'
Binary files data/media/goldflame/minute1.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute10.png'
Binary files data/media/goldflame/minute10.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute11.png'
Binary files data/media/goldflame/minute11.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute12.png'
Binary files data/media/goldflame/minute12.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute13.png'
Binary files data/media/goldflame/minute13.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute14.png'
Binary files data/media/goldflame/minute14.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute15.png'
Binary files data/media/goldflame/minute15.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute16.png'
Binary files data/media/goldflame/minute16.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute17.png'
Binary files data/media/goldflame/minute17.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute18.png'
Binary files data/media/goldflame/minute18.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute19.png'
Binary files data/media/goldflame/minute19.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute2.png'
Binary files data/media/goldflame/minute2.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute20.png'
Binary files data/media/goldflame/minute20.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute21.png'
Binary files data/media/goldflame/minute21.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute22.png'
Binary files data/media/goldflame/minute22.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute23.png'
Binary files data/media/goldflame/minute23.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute24.png'
Binary files data/media/goldflame/minute24.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute25.png'
Binary files data/media/goldflame/minute25.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute26.png'
Binary files data/media/goldflame/minute26.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute27.png'
Binary files data/media/goldflame/minute27.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute28.png'
Binary files data/media/goldflame/minute28.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute29.png'
Binary files data/media/goldflame/minute29.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute3.png'
Binary files data/media/goldflame/minute3.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute30.png'
Binary files data/media/goldflame/minute30.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute31.png'
Binary files data/media/goldflame/minute31.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute32.png'
Binary files data/media/goldflame/minute32.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute32.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute33.png'
Binary files data/media/goldflame/minute33.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute33.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute34.png'
Binary files data/media/goldflame/minute34.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute34.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute35.png'
Binary files data/media/goldflame/minute35.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute35.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute36.png'
Binary files data/media/goldflame/minute36.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute36.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute37.png'
Binary files data/media/goldflame/minute37.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute37.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute38.png'
Binary files data/media/goldflame/minute38.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute38.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute39.png'
Binary files data/media/goldflame/minute39.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute39.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute4.png'
Binary files data/media/goldflame/minute4.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute40.png'
Binary files data/media/goldflame/minute40.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute40.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute41.png'
Binary files data/media/goldflame/minute41.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute41.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute42.png'
Binary files data/media/goldflame/minute42.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute42.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute43.png'
Binary files data/media/goldflame/minute43.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute43.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute44.png'
Binary files data/media/goldflame/minute44.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute44.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute45.png'
Binary files data/media/goldflame/minute45.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute45.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute46.png'
Binary files data/media/goldflame/minute46.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute46.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute47.png'
Binary files data/media/goldflame/minute47.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute47.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute48.png'
Binary files data/media/goldflame/minute48.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute48.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute49.png'
Binary files data/media/goldflame/minute49.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute49.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute5.png'
Binary files data/media/goldflame/minute5.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute50.png'
Binary files data/media/goldflame/minute50.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute50.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute51.png'
Binary files data/media/goldflame/minute51.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute51.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute52.png'
Binary files data/media/goldflame/minute52.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute52.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute53.png'
Binary files data/media/goldflame/minute53.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute53.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute54.png'
Binary files data/media/goldflame/minute54.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute54.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute55.png'
Binary files data/media/goldflame/minute55.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute55.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute56.png'
Binary files data/media/goldflame/minute56.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute56.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute57.png'
Binary files data/media/goldflame/minute57.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute57.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute58.png'
Binary files data/media/goldflame/minute58.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute58.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute59.png'
Binary files data/media/goldflame/minute59.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute59.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute6.png'
Binary files data/media/goldflame/minute6.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute7.png'
Binary files data/media/goldflame/minute7.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute8.png'
Binary files data/media/goldflame/minute8.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/minute9.png'
Binary files data/media/goldflame/minute9.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/minute9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month1.png'
Binary files data/media/goldflame/month1.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month10.png'
Binary files data/media/goldflame/month10.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month11.png'
Binary files data/media/goldflame/month11.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month12.png'
Binary files data/media/goldflame/month12.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month2.png'
Binary files data/media/goldflame/month2.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month3.png'
Binary files data/media/goldflame/month3.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month4.png'
Binary files data/media/goldflame/month4.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month5.png'
Binary files data/media/goldflame/month5.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month6.png'
Binary files data/media/goldflame/month6.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month7.png'
Binary files data/media/goldflame/month7.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month8.png'
Binary files data/media/goldflame/month8.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/month9.png'
Binary files data/media/goldflame/month9.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/month9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/pm.png'
Binary files data/media/goldflame/pm.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/pm.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/preview100x75.jpg'
Binary files data/media/goldflame/preview100x75.jpg 1970-01-01 00:00:00 +0000 and data/media/goldflame/preview100x75.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/preview200x150.jpg'
Binary files data/media/goldflame/preview200x150.jpg 1970-01-01 00:00:00 +0000 and data/media/goldflame/preview200x150.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday1.png'
Binary files data/media/goldflame/weekday1.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday2.png'
Binary files data/media/goldflame/weekday2.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday3.png'
Binary files data/media/goldflame/weekday3.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday4.png'
Binary files data/media/goldflame/weekday4.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday5.png'
Binary files data/media/goldflame/weekday5.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday6.png'
Binary files data/media/goldflame/weekday6.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/goldflame/weekday7.png'
Binary files data/media/goldflame/weekday7.png 1970-01-01 00:00:00 +0000 and data/media/goldflame/weekday7.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/media/lcd_blue'
=== added file 'data/media/lcd_blue/am.png'
Binary files data/media/lcd_blue/am.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/am.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/bg.jpg'
Binary files data/media/lcd_blue/bg.jpg 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/bg.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/clock.ini'
--- data/media/lcd_blue/clock.ini 1970-01-01 00:00:00 +0000
+++ data/media/lcd_blue/clock.ini 2013-05-09 22:05:30 +0000
@@ -0,0 +1,19 @@
+[Settings]
+name=LCD Blue
+width=1366
+height=768
+author=Vlad Gerasimov
+email=vladstudio@xxxxxxxxx
+ampmenabled=1
+description=
+homepageURL=http://www.vladstudio.com
+downloadURL=http://www.vladstudio.com
+refreshhourinterval=60
+hourimages=24
+
+[Animation]
+
+[WallpaperClock]
+specVersion=1.0
+specampmenabled=1
+description=http://www.wallpaperclock.com/wcz/spec.php
\ No newline at end of file
=== added file 'data/media/lcd_blue/day1.png'
Binary files data/media/lcd_blue/day1.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day10.png'
Binary files data/media/lcd_blue/day10.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day11.png'
Binary files data/media/lcd_blue/day11.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day12.png'
Binary files data/media/lcd_blue/day12.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day13.png'
Binary files data/media/lcd_blue/day13.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day14.png'
Binary files data/media/lcd_blue/day14.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day15.png'
Binary files data/media/lcd_blue/day15.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day16.png'
Binary files data/media/lcd_blue/day16.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day17.png'
Binary files data/media/lcd_blue/day17.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day18.png'
Binary files data/media/lcd_blue/day18.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day19.png'
Binary files data/media/lcd_blue/day19.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day2.png'
Binary files data/media/lcd_blue/day2.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day20.png'
Binary files data/media/lcd_blue/day20.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day21.png'
Binary files data/media/lcd_blue/day21.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day22.png'
Binary files data/media/lcd_blue/day22.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day23.png'
Binary files data/media/lcd_blue/day23.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day24.png'
Binary files data/media/lcd_blue/day24.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day25.png'
Binary files data/media/lcd_blue/day25.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day26.png'
Binary files data/media/lcd_blue/day26.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day27.png'
Binary files data/media/lcd_blue/day27.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day28.png'
Binary files data/media/lcd_blue/day28.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day29.png'
Binary files data/media/lcd_blue/day29.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day3.png'
Binary files data/media/lcd_blue/day3.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day30.png'
Binary files data/media/lcd_blue/day30.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day31.png'
Binary files data/media/lcd_blue/day31.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day4.png'
Binary files data/media/lcd_blue/day4.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day5.png'
Binary files data/media/lcd_blue/day5.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day6.png'
Binary files data/media/lcd_blue/day6.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day7.png'
Binary files data/media/lcd_blue/day7.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day8.png'
Binary files data/media/lcd_blue/day8.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/day9.png'
Binary files data/media/lcd_blue/day9.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/day9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour0.png'
Binary files data/media/lcd_blue/hour0.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour1.png'
Binary files data/media/lcd_blue/hour1.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour10.png'
Binary files data/media/lcd_blue/hour10.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour11.png'
Binary files data/media/lcd_blue/hour11.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour12.png'
Binary files data/media/lcd_blue/hour12.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour13.png'
Binary files data/media/lcd_blue/hour13.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour14.png'
Binary files data/media/lcd_blue/hour14.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour15.png'
Binary files data/media/lcd_blue/hour15.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour16.png'
Binary files data/media/lcd_blue/hour16.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour17.png'
Binary files data/media/lcd_blue/hour17.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour18.png'
Binary files data/media/lcd_blue/hour18.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour19.png'
Binary files data/media/lcd_blue/hour19.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour2.png'
Binary files data/media/lcd_blue/hour2.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour20.png'
Binary files data/media/lcd_blue/hour20.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour21.png'
Binary files data/media/lcd_blue/hour21.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour22.png'
Binary files data/media/lcd_blue/hour22.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour23.png'
Binary files data/media/lcd_blue/hour23.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour3.png'
Binary files data/media/lcd_blue/hour3.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour4.png'
Binary files data/media/lcd_blue/hour4.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour5.png'
Binary files data/media/lcd_blue/hour5.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour6.png'
Binary files data/media/lcd_blue/hour6.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour7.png'
Binary files data/media/lcd_blue/hour7.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour8.png'
Binary files data/media/lcd_blue/hour8.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/hour9.png'
Binary files data/media/lcd_blue/hour9.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/hour9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute0.png'
Binary files data/media/lcd_blue/minute0.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute1.png'
Binary files data/media/lcd_blue/minute1.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute10.png'
Binary files data/media/lcd_blue/minute10.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute11.png'
Binary files data/media/lcd_blue/minute11.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute12.png'
Binary files data/media/lcd_blue/minute12.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute13.png'
Binary files data/media/lcd_blue/minute13.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute14.png'
Binary files data/media/lcd_blue/minute14.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute15.png'
Binary files data/media/lcd_blue/minute15.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute16.png'
Binary files data/media/lcd_blue/minute16.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute17.png'
Binary files data/media/lcd_blue/minute17.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute18.png'
Binary files data/media/lcd_blue/minute18.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute19.png'
Binary files data/media/lcd_blue/minute19.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute2.png'
Binary files data/media/lcd_blue/minute2.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute20.png'
Binary files data/media/lcd_blue/minute20.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute21.png'
Binary files data/media/lcd_blue/minute21.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute22.png'
Binary files data/media/lcd_blue/minute22.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute23.png'
Binary files data/media/lcd_blue/minute23.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute24.png'
Binary files data/media/lcd_blue/minute24.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute25.png'
Binary files data/media/lcd_blue/minute25.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute26.png'
Binary files data/media/lcd_blue/minute26.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute27.png'
Binary files data/media/lcd_blue/minute27.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute28.png'
Binary files data/media/lcd_blue/minute28.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute29.png'
Binary files data/media/lcd_blue/minute29.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute3.png'
Binary files data/media/lcd_blue/minute3.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute30.png'
Binary files data/media/lcd_blue/minute30.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute31.png'
Binary files data/media/lcd_blue/minute31.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute32.png'
Binary files data/media/lcd_blue/minute32.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute32.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute33.png'
Binary files data/media/lcd_blue/minute33.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute33.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute34.png'
Binary files data/media/lcd_blue/minute34.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute34.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute35.png'
Binary files data/media/lcd_blue/minute35.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute35.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute36.png'
Binary files data/media/lcd_blue/minute36.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute36.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute37.png'
Binary files data/media/lcd_blue/minute37.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute37.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute38.png'
Binary files data/media/lcd_blue/minute38.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute38.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute39.png'
Binary files data/media/lcd_blue/minute39.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute39.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute4.png'
Binary files data/media/lcd_blue/minute4.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute40.png'
Binary files data/media/lcd_blue/minute40.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute40.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute41.png'
Binary files data/media/lcd_blue/minute41.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute41.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute42.png'
Binary files data/media/lcd_blue/minute42.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute42.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute43.png'
Binary files data/media/lcd_blue/minute43.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute43.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute44.png'
Binary files data/media/lcd_blue/minute44.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute44.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute45.png'
Binary files data/media/lcd_blue/minute45.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute45.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute46.png'
Binary files data/media/lcd_blue/minute46.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute46.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute47.png'
Binary files data/media/lcd_blue/minute47.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute47.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute48.png'
Binary files data/media/lcd_blue/minute48.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute48.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute49.png'
Binary files data/media/lcd_blue/minute49.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute49.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute5.png'
Binary files data/media/lcd_blue/minute5.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute50.png'
Binary files data/media/lcd_blue/minute50.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute50.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute51.png'
Binary files data/media/lcd_blue/minute51.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute51.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute52.png'
Binary files data/media/lcd_blue/minute52.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute52.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute53.png'
Binary files data/media/lcd_blue/minute53.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute53.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute54.png'
Binary files data/media/lcd_blue/minute54.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute54.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute55.png'
Binary files data/media/lcd_blue/minute55.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute55.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute56.png'
Binary files data/media/lcd_blue/minute56.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute56.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute57.png'
Binary files data/media/lcd_blue/minute57.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute57.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute58.png'
Binary files data/media/lcd_blue/minute58.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute58.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute59.png'
Binary files data/media/lcd_blue/minute59.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute59.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute6.png'
Binary files data/media/lcd_blue/minute6.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute7.png'
Binary files data/media/lcd_blue/minute7.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute8.png'
Binary files data/media/lcd_blue/minute8.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/minute9.png'
Binary files data/media/lcd_blue/minute9.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/minute9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month1.png'
Binary files data/media/lcd_blue/month1.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month10.png'
Binary files data/media/lcd_blue/month10.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month11.png'
Binary files data/media/lcd_blue/month11.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month12.png'
Binary files data/media/lcd_blue/month12.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month2.png'
Binary files data/media/lcd_blue/month2.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month3.png'
Binary files data/media/lcd_blue/month3.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month4.png'
Binary files data/media/lcd_blue/month4.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month5.png'
Binary files data/media/lcd_blue/month5.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month6.png'
Binary files data/media/lcd_blue/month6.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month7.png'
Binary files data/media/lcd_blue/month7.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month8.png'
Binary files data/media/lcd_blue/month8.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/month9.png'
Binary files data/media/lcd_blue/month9.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/month9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/pm.png'
Binary files data/media/lcd_blue/pm.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/pm.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/preview100x75.jpg'
Binary files data/media/lcd_blue/preview100x75.jpg 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/preview100x75.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/preview200x150.jpg'
Binary files data/media/lcd_blue/preview200x150.jpg 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/preview200x150.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday1.png'
Binary files data/media/lcd_blue/weekday1.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday2.png'
Binary files data/media/lcd_blue/weekday2.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday3.png'
Binary files data/media/lcd_blue/weekday3.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday4.png'
Binary files data/media/lcd_blue/weekday4.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday5.png'
Binary files data/media/lcd_blue/weekday5.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday6.png'
Binary files data/media/lcd_blue/weekday6.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/lcd_blue/weekday7.png'
Binary files data/media/lcd_blue/weekday7.png 1970-01-01 00:00:00 +0000 and data/media/lcd_blue/weekday7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/map.png'
Binary files data/media/map.png 1970-01-01 00:00:00 +0000 and data/media/map.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/media/monitor'
=== added file 'data/media/monitor/monitor_centered.png'
Binary files data/media/monitor/monitor_centered.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_centered.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/monitor/monitor_scaled.png'
Binary files data/media/monitor/monitor_scaled.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_scaled.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/monitor/monitor_spanned.png'
Binary files data/media/monitor/monitor_spanned.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_spanned.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/monitor/monitor_stretched.png'
Binary files data/media/monitor/monitor_stretched.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_stretched.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/monitor/monitor_wallpaper.png'
Binary files data/media/monitor/monitor_wallpaper.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_wallpaper.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/monitor/monitor_zoom.png'
Binary files data/media/monitor/monitor_zoom.png 1970-01-01 00:00:00 +0000 and data/media/monitor/monitor_zoom.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/new.png'
Binary files data/media/new.png 1970-01-01 00:00:00 +0000 and data/media/new.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/media/radarblue'
=== added file 'data/media/radarblue/bg.jpg'
Binary files data/media/radarblue/bg.jpg 1970-01-01 00:00:00 +0000 and data/media/radarblue/bg.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/clock.ini'
--- data/media/radarblue/clock.ini 1970-01-01 00:00:00 +0000
+++ data/media/radarblue/clock.ini 2013-05-09 22:05:30 +0000
@@ -0,0 +1,19 @@
+[Settings]
+name=Radar Blue
+width=1440
+height=900
+author=Vlad Gerasimov
+email=vladstudio@xxxxxxxxx
+ampmenabled=0
+description=
+homepageURL=http://www.vladstudio.com
+downloadURL=http://www.vladstudio.com
+refreshhourinterval=12
+hourimages=60
+
+[Animation]
+
+[WallpaperClock]
+specVersion=1.0
+specampmenabled=0
+description=http://www.wallpaperclock.com/wcz/spec.php
\ No newline at end of file
=== added file 'data/media/radarblue/day1.png'
Binary files data/media/radarblue/day1.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day10.png'
Binary files data/media/radarblue/day10.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day11.png'
Binary files data/media/radarblue/day11.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day12.png'
Binary files data/media/radarblue/day12.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day13.png'
Binary files data/media/radarblue/day13.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day14.png'
Binary files data/media/radarblue/day14.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day15.png'
Binary files data/media/radarblue/day15.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day16.png'
Binary files data/media/radarblue/day16.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day17.png'
Binary files data/media/radarblue/day17.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day18.png'
Binary files data/media/radarblue/day18.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day19.png'
Binary files data/media/radarblue/day19.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day2.png'
Binary files data/media/radarblue/day2.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day20.png'
Binary files data/media/radarblue/day20.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day21.png'
Binary files data/media/radarblue/day21.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day22.png'
Binary files data/media/radarblue/day22.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day23.png'
Binary files data/media/radarblue/day23.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day24.png'
Binary files data/media/radarblue/day24.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day25.png'
Binary files data/media/radarblue/day25.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day26.png'
Binary files data/media/radarblue/day26.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day27.png'
Binary files data/media/radarblue/day27.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day28.png'
Binary files data/media/radarblue/day28.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day29.png'
Binary files data/media/radarblue/day29.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day3.png'
Binary files data/media/radarblue/day3.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day30.png'
Binary files data/media/radarblue/day30.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day31.png'
Binary files data/media/radarblue/day31.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day4.png'
Binary files data/media/radarblue/day4.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day5.png'
Binary files data/media/radarblue/day5.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day6.png'
Binary files data/media/radarblue/day6.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day7.png'
Binary files data/media/radarblue/day7.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day8.png'
Binary files data/media/radarblue/day8.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/day9.png'
Binary files data/media/radarblue/day9.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/day9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour0.png'
Binary files data/media/radarblue/hour0.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour1.png'
Binary files data/media/radarblue/hour1.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour10.png'
Binary files data/media/radarblue/hour10.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour11.png'
Binary files data/media/radarblue/hour11.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour12.png'
Binary files data/media/radarblue/hour12.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour13.png'
Binary files data/media/radarblue/hour13.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour14.png'
Binary files data/media/radarblue/hour14.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour15.png'
Binary files data/media/radarblue/hour15.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour16.png'
Binary files data/media/radarblue/hour16.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour17.png'
Binary files data/media/radarblue/hour17.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour18.png'
Binary files data/media/radarblue/hour18.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour19.png'
Binary files data/media/radarblue/hour19.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour2.png'
Binary files data/media/radarblue/hour2.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour20.png'
Binary files data/media/radarblue/hour20.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour21.png'
Binary files data/media/radarblue/hour21.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour22.png'
Binary files data/media/radarblue/hour22.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour23.png'
Binary files data/media/radarblue/hour23.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour24.png'
Binary files data/media/radarblue/hour24.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour25.png'
Binary files data/media/radarblue/hour25.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour26.png'
Binary files data/media/radarblue/hour26.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour27.png'
Binary files data/media/radarblue/hour27.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour28.png'
Binary files data/media/radarblue/hour28.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour29.png'
Binary files data/media/radarblue/hour29.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour3.png'
Binary files data/media/radarblue/hour3.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour30.png'
Binary files data/media/radarblue/hour30.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour31.png'
Binary files data/media/radarblue/hour31.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour32.png'
Binary files data/media/radarblue/hour32.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour32.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour33.png'
Binary files data/media/radarblue/hour33.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour33.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour34.png'
Binary files data/media/radarblue/hour34.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour34.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour35.png'
Binary files data/media/radarblue/hour35.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour35.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour36.png'
Binary files data/media/radarblue/hour36.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour36.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour37.png'
Binary files data/media/radarblue/hour37.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour37.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour38.png'
Binary files data/media/radarblue/hour38.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour38.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour39.png'
Binary files data/media/radarblue/hour39.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour39.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour4.png'
Binary files data/media/radarblue/hour4.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour40.png'
Binary files data/media/radarblue/hour40.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour40.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour41.png'
Binary files data/media/radarblue/hour41.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour41.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour42.png'
Binary files data/media/radarblue/hour42.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour42.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour43.png'
Binary files data/media/radarblue/hour43.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour43.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour44.png'
Binary files data/media/radarblue/hour44.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour44.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour45.png'
Binary files data/media/radarblue/hour45.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour45.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour46.png'
Binary files data/media/radarblue/hour46.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour46.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour47.png'
Binary files data/media/radarblue/hour47.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour47.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour48.png'
Binary files data/media/radarblue/hour48.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour48.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour49.png'
Binary files data/media/radarblue/hour49.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour49.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour5.png'
Binary files data/media/radarblue/hour5.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour50.png'
Binary files data/media/radarblue/hour50.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour50.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour51.png'
Binary files data/media/radarblue/hour51.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour51.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour52.png'
Binary files data/media/radarblue/hour52.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour52.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour53.png'
Binary files data/media/radarblue/hour53.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour53.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour54.png'
Binary files data/media/radarblue/hour54.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour54.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour55.png'
Binary files data/media/radarblue/hour55.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour55.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour56.png'
Binary files data/media/radarblue/hour56.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour56.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour57.png'
Binary files data/media/radarblue/hour57.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour57.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour58.png'
Binary files data/media/radarblue/hour58.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour58.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour59.png'
Binary files data/media/radarblue/hour59.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour59.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour6.png'
Binary files data/media/radarblue/hour6.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour7.png'
Binary files data/media/radarblue/hour7.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour8.png'
Binary files data/media/radarblue/hour8.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/hour9.png'
Binary files data/media/radarblue/hour9.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/hour9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute0.png'
Binary files data/media/radarblue/minute0.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute1.png'
Binary files data/media/radarblue/minute1.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute10.png'
Binary files data/media/radarblue/minute10.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute11.png'
Binary files data/media/radarblue/minute11.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute12.png'
Binary files data/media/radarblue/minute12.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute13.png'
Binary files data/media/radarblue/minute13.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute14.png'
Binary files data/media/radarblue/minute14.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute15.png'
Binary files data/media/radarblue/minute15.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute16.png'
Binary files data/media/radarblue/minute16.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute17.png'
Binary files data/media/radarblue/minute17.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute18.png'
Binary files data/media/radarblue/minute18.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute19.png'
Binary files data/media/radarblue/minute19.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute2.png'
Binary files data/media/radarblue/minute2.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute20.png'
Binary files data/media/radarblue/minute20.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute21.png'
Binary files data/media/radarblue/minute21.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute22.png'
Binary files data/media/radarblue/minute22.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute23.png'
Binary files data/media/radarblue/minute23.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute24.png'
Binary files data/media/radarblue/minute24.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute25.png'
Binary files data/media/radarblue/minute25.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute26.png'
Binary files data/media/radarblue/minute26.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute27.png'
Binary files data/media/radarblue/minute27.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute28.png'
Binary files data/media/radarblue/minute28.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute29.png'
Binary files data/media/radarblue/minute29.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute3.png'
Binary files data/media/radarblue/minute3.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute30.png'
Binary files data/media/radarblue/minute30.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute31.png'
Binary files data/media/radarblue/minute31.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute32.png'
Binary files data/media/radarblue/minute32.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute32.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute33.png'
Binary files data/media/radarblue/minute33.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute33.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute34.png'
Binary files data/media/radarblue/minute34.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute34.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute35.png'
Binary files data/media/radarblue/minute35.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute35.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute36.png'
Binary files data/media/radarblue/minute36.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute36.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute37.png'
Binary files data/media/radarblue/minute37.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute37.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute38.png'
Binary files data/media/radarblue/minute38.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute38.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute39.png'
Binary files data/media/radarblue/minute39.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute39.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute4.png'
Binary files data/media/radarblue/minute4.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute40.png'
Binary files data/media/radarblue/minute40.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute40.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute41.png'
Binary files data/media/radarblue/minute41.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute41.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute42.png'
Binary files data/media/radarblue/minute42.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute42.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute43.png'
Binary files data/media/radarblue/minute43.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute43.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute44.png'
Binary files data/media/radarblue/minute44.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute44.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute45.png'
Binary files data/media/radarblue/minute45.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute45.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute46.png'
Binary files data/media/radarblue/minute46.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute46.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute47.png'
Binary files data/media/radarblue/minute47.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute47.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute48.png'
Binary files data/media/radarblue/minute48.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute48.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute49.png'
Binary files data/media/radarblue/minute49.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute49.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute5.png'
Binary files data/media/radarblue/minute5.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute50.png'
Binary files data/media/radarblue/minute50.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute50.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute51.png'
Binary files data/media/radarblue/minute51.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute51.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute52.png'
Binary files data/media/radarblue/minute52.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute52.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute53.png'
Binary files data/media/radarblue/minute53.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute53.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute54.png'
Binary files data/media/radarblue/minute54.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute54.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute55.png'
Binary files data/media/radarblue/minute55.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute55.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute56.png'
Binary files data/media/radarblue/minute56.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute56.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute57.png'
Binary files data/media/radarblue/minute57.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute57.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute58.png'
Binary files data/media/radarblue/minute58.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute58.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute59.png'
Binary files data/media/radarblue/minute59.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute59.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute6.png'
Binary files data/media/radarblue/minute6.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute7.png'
Binary files data/media/radarblue/minute7.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute8.png'
Binary files data/media/radarblue/minute8.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/minute9.png'
Binary files data/media/radarblue/minute9.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/minute9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month1.png'
Binary files data/media/radarblue/month1.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month10.png'
Binary files data/media/radarblue/month10.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month11.png'
Binary files data/media/radarblue/month11.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month12.png'
Binary files data/media/radarblue/month12.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month2.png'
Binary files data/media/radarblue/month2.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month3.png'
Binary files data/media/radarblue/month3.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month4.png'
Binary files data/media/radarblue/month4.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month5.png'
Binary files data/media/radarblue/month5.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month6.png'
Binary files data/media/radarblue/month6.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month7.png'
Binary files data/media/radarblue/month7.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month8.png'
Binary files data/media/radarblue/month8.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/month9.png'
Binary files data/media/radarblue/month9.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/month9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/preview100x75.jpg'
Binary files data/media/radarblue/preview100x75.jpg 1970-01-01 00:00:00 +0000 and data/media/radarblue/preview100x75.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/preview200x150.jpg'
Binary files data/media/radarblue/preview200x150.jpg 1970-01-01 00:00:00 +0000 and data/media/radarblue/preview200x150.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday1.png'
Binary files data/media/radarblue/weekday1.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday2.png'
Binary files data/media/radarblue/weekday2.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday3.png'
Binary files data/media/radarblue/weekday3.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday4.png'
Binary files data/media/radarblue/weekday4.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday5.png'
Binary files data/media/radarblue/weekday5.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday6.png'
Binary files data/media/radarblue/weekday6.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/radarblue/weekday7.png'
Binary files data/media/radarblue/weekday7.png 1970-01-01 00:00:00 +0000 and data/media/radarblue/weekday7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/random.png'
Binary files data/media/random.png 1970-01-01 00:00:00 +0000 and data/media/random.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/slidewall.png'
Binary files data/media/slidewall.png 1970-01-01 00:00:00 +0000 and data/media/slidewall.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/slidewall.svg'
--- data/media/slidewall.svg 1970-01-01 00:00:00 +0000
+++ data/media/slidewall.svg 2013-05-09 22:05:30 +0000
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48.000000px" height="48.000000px" id="svg2327" sodipodi:version="0.32" inkscape:version="0.46" sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/apps" sodipodi:docname="preferences-desktop-wallpaper.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs3">
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 24 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="48 : 24 : 1" inkscape:persp3d-origin="24 : 16 : 1" id="perspective115"/>
+ <linearGradient inkscape:collect="always" id="linearGradient2399">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop2401"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop2403"/>
+ </linearGradient>
+ <linearGradient id="linearGradient4930">
+ <stop style="stop-color:#babdb6;stop-opacity:1;" offset="0" id="stop4932"/>
+ <stop style="stop-color:#50544c;stop-opacity:1;" offset="1" id="stop4934"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient4920">
+ <stop style="stop-color:#2c65b9;stop-opacity:1;" offset="0" id="stop4922"/>
+ <stop style="stop-color:#2c65b9;stop-opacity:0;" offset="1" id="stop4924"/>
+ </linearGradient>
+ <linearGradient id="linearGradient4910">
+ <stop style="stop-color:#6a6352;stop-opacity:1;" offset="0" id="stop4912"/>
+ <stop style="stop-color:#3b372e;stop-opacity:1;" offset="1" id="stop4914"/>
+ </linearGradient>
+ <linearGradient id="linearGradient4902">
+ <stop style="stop-color:#204a87;stop-opacity:1;" offset="0" id="stop4904"/>
+ <stop style="stop-color:#173561;stop-opacity:1;" offset="1" id="stop4906"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient4892">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop4894"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop4896"/>
+ </linearGradient>
+ <linearGradient id="linearGradient4882">
+ <stop style="stop-color:#e7e5e0;stop-opacity:1;" offset="0" id="stop4884"/>
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="1" id="stop4886"/>
+ </linearGradient>
+ <linearGradient id="linearGradient4872">
+ <stop style="stop-color:#e5d28f;stop-opacity:1;" offset="0" id="stop4874"/>
+ <stop style="stop-color:#ab8f2a;stop-opacity:1;" offset="1" id="stop4876"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2329">
+ <stop id="stop2331" offset="0.0000000" style="stop-color:#ffffff;stop-opacity:1.0000000;"/>
+ <stop id="stop2333" offset="1.0000000" style="stop-color:#ffffff;stop-opacity:0.0000000;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2321" inkscape:collect="always">
+ <stop id="stop2323" offset="0" style="stop-color:#7b7f7a;stop-opacity:1;"/>
+ <stop id="stop2325" offset="1" style="stop-color:#7b7f7a;stop-opacity:0;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2711">
+ <stop id="stop2713" offset="0.0000000" style="stop-color:#909090;stop-opacity:1.0000000;"/>
+ <stop id="stop2715" offset="1.0000000" style="stop-color:#bebebe;stop-opacity:0.0000000;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2701">
+ <stop id="stop2703" offset="0.0000000" style="stop-color:#585956;stop-opacity:1.0000000;"/>
+ <stop id="stop2705" offset="1.0000000" style="stop-color:#bbbeb8;stop-opacity:1.0000000;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2683" inkscape:collect="always">
+ <stop id="stop2685" offset="0" style="stop-color:#000000;stop-opacity:1;"/>
+ <stop id="stop2687" offset="1" style="stop-color:#000000;stop-opacity:0;"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2667">
+ <stop id="stop2669" offset="0.0000000" style="stop-color:#ffffff;stop-opacity:1.0000000;"/>
+ <stop id="stop2671" offset="1.0000000" style="stop-color:#fcfcff;stop-opacity:0.0000000;"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient2454">
+ <stop style="stop-color:#000000;stop-opacity:1;" offset="0" id="stop2456"/>
+ <stop style="stop-color:#000000;stop-opacity:0;" offset="1" id="stop2458"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient2415">
+ <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop2417"/>
+ <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop2419"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2253">
+ <stop style="stop-color:#8f8f8f;stop-opacity:1.0000000;" offset="0.0000000" id="stop2255"/>
+ <stop style="stop-color:#494949;stop-opacity:1.0000000;" offset="1.0000000" id="stop2257"/>
+ </linearGradient>
+ <linearGradient id="linearGradient2245">
+ <stop style="stop-color:#dde1d9;stop-opacity:1.0000000;" offset="0.0000000" id="stop2247"/>
+ <stop style="stop-color:#cacdc6;stop-opacity:1.0000000;" offset="1.0000000" id="stop2249"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2245" id="linearGradient2251" gradientTransform="matrix(1.129863,0.000000,0.000000,0.885063,2.875000,1.570628)" x1="8.6116238" y1="7.2293582" x2="34.784473" y2="33.339787" gradientUnits="userSpaceOnUse"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2415" id="linearGradient2421" gradientTransform="matrix(1.108069,0.000000,0.000000,0.902471,5.500000,3.875000)" x1="17.698339" y1="13.004725" x2="34.974548" y2="55.200756" gradientUnits="userSpaceOnUse"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient2454" id="radialGradient2460" gradientTransform="scale(1.925808,0.519262)" cx="12.575710" cy="67.501709" fx="12.575710" fy="67.501709" r="8.7662794" gradientUnits="userSpaceOnUse"/>
+ <linearGradient gradientUnits="userSpaceOnUse" y2="162.45061" x2="3.7069974" y1="171.29134" x1="3.7069976" gradientTransform="matrix(5.705159,0.000000,0.000000,0.175280,5.500000,2.195627)" id="linearGradient2689" xlink:href="#linearGradient2683" inkscape:collect="always"/>
+ <linearGradient gradientUnits="userSpaceOnUse" y2="64.892525" x2="12.127711" y1="53.535141" x1="12.206709" gradientTransform="matrix(1.816345,0.000000,0.000000,1.278927,2.500000,-40.24508)" id="linearGradient2707" xlink:href="#linearGradient2701" inkscape:collect="always"/>
+ <linearGradient gradientUnits="userSpaceOnUse" y2="3.8451097" x2="35.520542" y1="3.9384086" x1="34.300991" id="linearGradient2717" xlink:href="#linearGradient2711" inkscape:collect="always"/>
+ <linearGradient y2="3.8451097" x2="35.520542" y1="3.9384086" x1="34.300991" gradientUnits="userSpaceOnUse" id="linearGradient2721" xlink:href="#linearGradient2711" inkscape:collect="always"/>
+ <linearGradient y2="3.8451097" x2="35.520542" y1="3.9384086" x1="34.300991" gradientUnits="userSpaceOnUse" id="linearGradient2725" xlink:href="#linearGradient2711" inkscape:collect="always"/>
+ <linearGradient y2="3.8451097" x2="35.520542" y1="3.9384086" x1="34.300991" gradientUnits="userSpaceOnUse" id="linearGradient2729" xlink:href="#linearGradient2711" inkscape:collect="always"/>
+ <linearGradient y2="3.8451097" x2="35.520542" y1="3.9384086" x1="34.300991" gradientUnits="userSpaceOnUse" id="linearGradient2733" xlink:href="#linearGradient2711" inkscape:collect="always"/>
+ <linearGradient y2="31.246054" x2="32.536823" y1="5.3817744" x1="10.390738" gradientTransform="matrix(1.104397,0.000000,0.000000,0.905471,4.500000,2.875000)" gradientUnits="userSpaceOnUse" id="linearGradient1561" xlink:href="#linearGradient2253" inkscape:collect="always"/>
+ <linearGradient gradientUnits="userSpaceOnUse" y2="28.205938" x2="-35.658386" y1="33.416473" x1="-35.658386" id="linearGradient2327" xlink:href="#linearGradient2321" inkscape:collect="always"/>
+ <linearGradient gradientUnits="userSpaceOnUse" y2="30.962345" x2="-35.074745" y1="34.242237" x1="-35.122688" id="linearGradient2337" xlink:href="#linearGradient2329" inkscape:collect="always"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2667" id="linearGradient2315" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.238977,0.000000,0.000000,0.895955,5.142330,1.543480)" x1="11.492236" y1="1.6537577" x2="17.199417" y2="26.729263"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4902" id="linearGradient4908" x1="21.6875" y1="12.093906" x2="21.6875" y2="7.7189064" gradientUnits="userSpaceOnUse" gradientTransform="translate(-0.707105,0.000000)"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4930" id="linearGradient4936" x1="23.493534" y1="29.476145" x2="23.493534" y2="6.9308271" gradientUnits="userSpaceOnUse"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2399" id="linearGradient2405" x1="19.489631" y1="15.23002" x2="20.727066" y2="14.876466" gradientUnits="userSpaceOnUse" gradientTransform="translate(-0.707105,0.000000)"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient2399" id="linearGradient2425" gradientUnits="userSpaceOnUse" x1="16.528622" y1="11.539805" x2="17.279921" y2="11.407223" gradientTransform="translate(-0.707105,0.000000)"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient2454" id="radialGradient2438" gradientUnits="userSpaceOnUse" gradientTransform="scale(1.925808,0.519262)" cx="12.575710" cy="67.501709" fx="12.575710" fy="67.501709" r="8.7662794"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4910" id="linearGradient2440" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.084646,-2.584738e-16)" x1="22.0625" y1="20.90625" x2="24.673225" y2="20.90625"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient4872" id="radialGradient2442" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.000000,0.000000,0.000000,1.281250,1.084646,-9.461426)" cx="28.0625" cy="36.908916" fx="28.0625" fy="36.908916" r="7.5"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4892" id="linearGradient2444" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.084646,-2.584738e-16)" x1="28.513193" y1="37.765625" x2="28.421637" y2="30.828125"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4882" id="linearGradient2446" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.000000,0.000000,0.000000,0.876289,1.084646,3.151418)" x1="28.625" y1="25.296875" x2="28.625" y2="28"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient4920" id="linearGradient2448" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.084646,-2.584738e-16)" x1="27.90625" y1="18.057989" x2="28.84375" y2="21.214239"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="0.12156863" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="11.313708" inkscape:cx="12.517984" inkscape:cy="23.29136" inkscape:current-layer="layer1" showgrid="false" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="914" inkscape:window-height="745" inkscape:window-x="315" inkscape:window-y="103" inkscape:showpageshadow="false" fill="#babdb6" stroke="#555753"/>
+ <metadata id="metadata4">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title>Wallpaper</dc:title>
+ <dc:date/>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>wallpaper</rdf:li>
+ <rdf:li>background</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <cc:license rdf:resource="http://creativecommons.org/licenses/publicdomain/"/>
+ <dc:source>http://jimmac.musichall.cz/</dc:source>
+ </cc:Work>
+ <cc:License rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
+ <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
+ <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
+ <path sodipodi:type="arc" style="opacity:0.50857143;overflow:visible;display:inline;visibility:visible;stroke-opacity:0.70063692;stroke-dashoffset:0.0000000;stroke-miterlimit:4.0000000;marker-end:none;marker-mid:none;marker-start:none;marker:none;stroke-linejoin:miter;stroke-linecap:round;stroke-width:1.0000000;stroke:none;fill-rule:evenodd;fill-opacity:1.0000000;fill:url(#radialGradient2460);color:#000000" id="path2452" sodipodi:cx="24.218407" sodipodi:cy="35.051105" sodipodi:rx="16.882174" sodipodi:ry="4.5520000" d="M 41.100580 35.051105 A 16.882174 4.5520000 0 1 1 7.3362331,35.051105 A 16.882174 4.5520000 0 1 1 41.100580 35.051105 z" transform="matrix(1.050251,0.000000,0.000000,1.867888,-0.945558,-28.10611)"/>
+ <path sodipodi:type="arc" style="color:#000000;fill:#adb0aa;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#4b4d4a;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" id="path2407" sodipodi:cx="-35.658386" sodipodi:cy="29.716238" sodipodi:rx="9.3944187" sodipodi:ry="3.9395950" d="M -26.263968 29.716238 A 9.3944187 3.9395950 0 1 1 -45.052805,29.716238 A 9.3944187 3.9395950 0 1 1 -26.263968 29.716238 z" transform="translate(60.03339,8.078430)"/>
+ <path transform="matrix(0.902373,0.000000,0.000000,0.827650,56.55215,12.86792)" d="M -26.263968 29.716238 A 9.3944187 3.9395950 0 1 1 -45.052805,29.716238 A 9.3944187 3.9395950 0 1 1 -26.263968 29.716238 z" sodipodi:ry="3.9395950" sodipodi:rx="9.3944187" sodipodi:cy="29.716238" sodipodi:cx="-35.658386" id="path1825" style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2327);stroke-width:1.1571338;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ <path sodipodi:type="arc" style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2337);stroke-width:1.1833371;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" id="path2983" sodipodi:cx="-35.658386" sodipodi:cy="29.716238" sodipodi:rx="9.3944187" sodipodi:ry="3.9395950" d="M -26.263968 29.716238 A 9.3944187 3.9395950 0 1 1 -45.052805,29.716238 A 9.3944187 3.9395950 0 1 1 -26.263968 29.716238 z" transform="matrix(0.837548,0.000000,0.000000,0.852655,54.17811,11.00615)"/>
+ <rect y="31.078613" x="19.972397" height="6.3650389" width="9.0396729" id="rect2699" style="color:#000000;fill:url(#linearGradient2707);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.60872948;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
+ <path style="color:#000000;fill:url(#linearGradient2251);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient1561);stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" d="M 7.5809024,4.5706221 L 41.169097,4.5706221 C 42.080439,4.5706221 42.793244,5.1541039 42.835849,5.9722091 L 44.167893,31.550323 C 44.226102,32.668058 43.266837,33.570628 42.147588,33.570628 L 6.6024120,33.570628 C 5.4831629,33.570628 4.5238980,32.668058 4.5821068,31.550323 L 5.9141506,5.9722091 C 5.9544343,5.1986745 6.4616533,4.5706221 7.5809024,4.5706221 z " id="rect2404" sodipodi:nodetypes="cssssssss"/>
+ <path sodipodi:nodetypes="ccccc" id="path2377" d="M 8.9105350,7.1808270 L 7.6683398,29.226144 L 39.318729,29.226144 L 37.983712,7.2742560 L 8.9105350,7.1808270 z " style="fill:url(#linearGradient4936);fill-opacity:1.0;fill-rule:evenodd;stroke:#555753;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"/>
+ <path sodipodi:nodetypes="cc" style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient2689);stroke-width:0.99618119;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.24840762" d="M 6.6774331,31.610789 L 42.105910,31.610789" id="path2393"/>
+ <path sodipodi:nodetypes="cssssssss" id="path2397" d="M 7.4145985,5.5813396 L 41.260101,5.5435383 C 41.543798,5.5432214 41.819403,5.7807881 41.842206,6.1960820 L 43.204098,30.999330 C 43.262137,32.056361 42.664349,32.785201 41.605727,32.785201 L 7.0817583,32.785201 C 6.0231355,32.785201 5.4887439,32.056410 5.5458869,30.999330 L 6.8699773,6.5051630 C 6.9086732,5.7893326 7.0363626,5.5817620 7.4145985,5.5813396 z " style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2421);stroke-width:0.99999964;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.70063692;visibility:visible;display:inline;overflow:visible"/>
+ <path transform="matrix(1.331237,0.000000,0.000000,0.658449,-5.919330,5.728866)" d="M 35.620504 3.9384086 A 0.83968931 0.83968931 0 1 1 33.941126,3.9384086 A 0.83968931 0.83968931 0 1 1 35.620504 3.9384086 z" sodipodi:ry="0.83968931" sodipodi:rx="0.83968931" sodipodi:cy="3.9384086" sodipodi:cx="34.780815" id="path2709" style="color:#000000;fill:url(#linearGradient2717);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ <path sodipodi:type="arc" style="color:#000000;fill:url(#linearGradient2721);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" id="path2719" sodipodi:cx="34.780815" sodipodi:cy="3.9384086" sodipodi:rx="0.83968931" sodipodi:ry="0.83968931" d="M 35.620504 3.9384086 A 0.83968931 0.83968931 0 1 1 33.941126,3.9384086 A 0.83968931 0.83968931 0 1 1 35.620504 3.9384086 z" transform="matrix(1.331237,0.000000,0.000000,0.658449,-5.805730,7.834650)"/>
+ <path transform="matrix(1.331237,0.000000,0.000000,0.658449,-5.692130,9.834650)" d="M 35.620504 3.9384086 A 0.83968931 0.83968931 0 1 1 33.941126,3.9384086 A 0.83968931 0.83968931 0 1 1 35.620504 3.9384086 z" sodipodi:ry="0.83968931" sodipodi:rx="0.83968931" sodipodi:cy="3.9384086" sodipodi:cx="34.780815" id="path2723" style="color:#000000;fill:url(#linearGradient2725);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ <path sodipodi:type="arc" style="color:#000000;fill:url(#linearGradient2729);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" id="path2727" sodipodi:cx="34.780815" sodipodi:cy="3.9384086" sodipodi:rx="0.83968931" sodipodi:ry="0.83968931" d="M 35.620504 3.9384086 A 0.83968931 0.83968931 0 1 1 33.941126,3.9384086 A 0.83968931 0.83968931 0 1 1 35.620504 3.9384086 z" transform="matrix(1.331237,0.000000,0.000000,0.658449,-5.578530,11.83465)"/>
+ <path transform="matrix(1.331237,0.000000,0.000000,0.658449,-5.464930,13.83465)" d="M 35.620504 3.9384086 A 0.83968931 0.83968931 0 1 1 33.941126,3.9384086 A 0.83968931 0.83968931 0 1 1 35.620504 3.9384086 z" sodipodi:ry="0.83968931" sodipodi:rx="0.83968931" sodipodi:cy="3.9384086" sodipodi:cx="34.780815" id="path2731" style="color:#000000;fill:url(#linearGradient2733);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ <path sodipodi:nodetypes="ccccc" style="opacity:0.53142856;fill:url(#linearGradient2315);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.25pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="M 9.263312,7.621363 L 8.460783,25.491693 C 19.505421,23.091063 23.882246,14.999494 37.614815,12.344943 L 37.453343,7.687427 L 9.263312,7.621363 z " id="path2443"/>
+ <path style="opacity:1;color:#000000;fill:url(#linearGradient4908);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" d="M 12.752542,7.3749999 C 12.752542,7.3749999 13.065042,16.296875 13.065042,17.125 C 13.065042,17.890625 12.346292,19.15625 13.315042,19.15625 C 14.221292,19.15625 13.502542,17.859375 13.565042,17.125 C 13.622263,16.452655 13.752542,12.25 13.752542,12.25 C 13.752542,12.25 14.440042,12.34375 14.752542,11.4375 C 15.065042,10.53125 15.002542,8.625 15.002542,8.625 L 15.502542,9.375 C 16.502542,16 16.038265,20.218918 16.065042,20.71875 C 16.08848,21.15625 15.345878,23.125 16.377542,23.125 C 17.690456,23.125 16.735096,21.21082 16.752542,20.75 C 16.77117,20.257973 16.903748,16.640625 17.627542,12.375 C 18.726336,13.984375 18.042896,10.875 19.292896,17.5 L 34.417896,18.875 C 34.167896,12.25 32.002542,8.625 30.502542,7.4999999 C 30.502542,7.4999999 12.752542,7.3749999 12.752542,7.3749999 z " id="path3523" sodipodi:nodetypes="czzzcscczzzcccsc"/>
+ <path transform="matrix(0.333333,0.000000,0.000000,0.333333,6.558675,10.20833)" d="M 30.25 36.5 A 1.125 1.125 0 1 1 28,36.5 A 1.125 1.125 0 1 1 30.25 36.5 z" sodipodi:ry="1.125" sodipodi:rx="1.125" sodipodi:cy="36.5" sodipodi:cx="29.125" id="path4938" style="opacity:0.51461989;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ <path sodipodi:type="arc" style="opacity:0.51461989;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" id="path4940" sodipodi:cx="29.125" sodipodi:cy="36.5" sodipodi:rx="1.125" sodipodi:ry="1.125" d="M 30.25 36.5 A 1.125 1.125 0 1 1 28,36.5 A 1.125 1.125 0 1 1 30.25 36.5 z" transform="matrix(0.250001,0.000000,0.000000,0.250001,5.892011,9.500001)"/>
+ <path style="opacity:0.51461989;color:#000000;fill:url(#linearGradient2405);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" d="M 18.672042,12.998214 L 19.66641,17.329243 L 20.461905,17.019884 C 20.461905,17.019884 19.865284,13.970486 19.290759,13.219185 C 18.716235,12.467884 18.60575,12.777243 18.009129,12.600467 C 18.009129,12.600467 18.451071,12.666758 18.672042,12.998214 z " id="path1524" sodipodi:nodetypes="cccscc"/>
+ <g id="g2427" transform="matrix(1.124849,0.000000,0.000000,1.124849,-4.096023,-3.071291)">
+ <path style="font-size:0.9029026px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;writing-mode:lr-tb;text-anchor:start;fill:#4a4a4a;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" d="M 23.584646,30.192666 L 23.866362,30.192666 C 23.950127,30.192667 24.014347,30.21133 24.059022,30.248656 C 24.103991,30.28569 24.126475,30.338594 24.126476,30.40737 C 24.126475,30.47644 24.103991,30.529638 24.059022,30.566965 C 24.014347,30.603998 23.950127,30.622515 23.866362,30.622515 L 23.754381,30.622515 L 23.754381,30.850885 L 23.584646,30.850885 L 23.584646,30.192666 M 23.754381,30.315669 L 23.754381,30.499512 L 23.848286,30.499512 C 23.881204,30.499512 23.906628,30.491576 23.924557,30.475705 C 23.942485,30.45954 23.95145,30.436762 23.95145,30.40737 C 23.95145,30.377979 23.942485,30.355348 23.924557,30.339476 C 23.906628,30.323605 23.881204,30.315669 23.848286,30.315669 L 23.754381,30.315669 M 24.546625,30.303765 C 24.494896,30.303766 24.454777,30.32287 24.426267,30.361078 C 24.397758,30.399288 24.383503,30.453074 24.383503,30.522437 C 24.383503,30.591507 24.397758,30.645146 24.426267,30.683355 C 24.454777,30.721564 24.494896,30.740668 24.546625,30.740668 C 24.598647,30.740668 24.638913,30.721564 24.667424,30.683355 C 24.695933,30.645146 24.710187,30.591507 24.710188,30.522437 C 24.710187,30.453074 24.695933,30.399288 24.667424,30.361078 C 24.638913,30.32287 24.598647,30.303766 24.546625,30.303765 M 24.546625,30.180762 C 24.652433,30.180763 24.735317,30.211036 24.795276,30.271582 C 24.855234,30.332128 24.885213,30.415747 24.885214,30.522437 C 24.885213,30.628834 24.855234,30.712305 24.795276,30.772851 C 24.735317,30.833398 24.652433,30.863671 24.546625,30.863671 C 24.44111,30.863671 24.358226,30.833398 24.297974,30.772851 C 24.238016,30.712305 24.208037,30.628834 24.208037,30.522437 C 24.208037,30.415747 24.238016,30.332128 24.297974,30.271582 C 24.358226,30.211036 24.44111,30.180763 24.546625,30.180762 M 25.013066,30.192666 L 25.20264,30.192666 L 25.442033,30.644117 L 25.442033,30.192666 L 25.602951,30.192666 L 25.602951,30.850885 L 25.413376,30.850885 L 25.173984,30.399434 L 25.173984,30.850885 L 25.013066,30.850885 L 25.013066,30.192666 M 25.676135,30.192666 L 25.861741,30.192666 L 26.011637,30.427209 L 26.161533,30.192666 L 26.347581,30.192666 L 26.096725,30.573578 L 26.096725,30.850885 L 25.92699,30.850885 L 25.92699,30.573578 L 25.676135,30.192666" id="text2735"/>
+ <path sodipodi:type="arc" style="opacity:0.20467834;color:#000000;fill:url(#radialGradient2438);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.70063692;visibility:visible;display:inline;overflow:visible" id="path3994" sodipodi:cx="24.218407" sodipodi:cy="35.051105" sodipodi:rx="16.882174" sodipodi:ry="4.552" d="M 41.10058 35.051105 A 16.882174 4.552 0 1 1 7.3362331,35.051105 A 16.882174 4.552 0 1 1 41.10058 35.051105 z" transform="matrix(0.531953,0.000000,0.000000,0.657752,17.94145,18.44946)"/>
+ <path sodipodi:nodetypes="cczccsccsccscsc" id="path4900" d="M 23.397146,24.5 L 36.397146,24.5 C 36.397146,24.5 36.584646,19.75 35.334646,18.5625 C 34.148705,17.435856 32.459646,17.6875 32.459646,17.6875 L 32.397146,18.1875 C 32.397146,18.1875 31.772146,17.75 30.647146,17.6875 C 29.522146,17.625 28.709646,17.75 28.709646,17.75 L 29.084646,18.125 C 29.084646,18.125 27.522146,17.5 26.022146,17.5 C 24.522146,17.5 24.209646,17.5625 24.209646,17.5625 L 24.772146,17.875 C 24.772146,17.875 23.522146,17.3125 22.522146,17.3125 C 21.522146,17.3125 20.647146,17.75 20.647146,17.75 C 20.647146,17.75 22.084646,18.5 22.647146,19.5 C 23.209646,20.5 23.397146,24.5 23.397146,24.5 z " style="opacity:1;color:#000000;fill:url(#linearGradient2440);fill-opacity:1;fill-rule:nonzero;stroke:#3a3a3a;stroke-width:0.88900858;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"/>
+ <path sodipodi:nodetypes="ccccszsccccc" id="rect4400" d="M 22.709646,24.53125 L 22.709646,28.90625 C 22.709646,29.854448 23.480199,30.625 24.428396,30.625 L 27.678396,30.625 C 27.439137,33.023287 26.965911,34.831157 27.084646,36.915354 C 27.159021,38.220887 28.2901,39.915354 30.084646,39.915354 C 31.691819,39.915354 32.847561,38.348829 32.959646,36.790354 C 33.084646,35.052311 32.306052,33.027831 31.959646,30.625 L 34.990896,30.625 C 35.939096,30.625 36.709646,29.854447 36.709646,28.90625 L 36.709646,24.53125 C 36.709646,24.53125 22.709646,24.53125 22.709646,24.53125 z " style="opacity:1;color:#000000;fill:url(#radialGradient2442);fill-opacity:1;fill-rule:nonzero;stroke:#80754c;stroke-width:0.88900858;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"/>
+ <path style="opacity:0.57309941;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2444);stroke-width:0.88900858;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" d="M 28.709646,29.415625 C 28.518239,31.334255 27.818213,34.838621 27.913201,36.505979 C 27.972701,37.550405 28.574009,38.984557 30.009646,38.984557 C 31.295384,38.984557 31.962845,37.715259 32.052513,36.468479 C 32.152513,35.078045 31.286771,31.33789 31.009646,29.415625 L 28.709646,29.415625 z " id="path4890" sodipodi:nodetypes="cszscc"/>
+ <path style="opacity:1;color:#000000;fill:#e8daa5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" d="M 23.209646,24.982422 L 23.209646,28.779297 C 23.209646,29.60897 23.82138,30.126953 24.651052,30.126953 L 34.83074,30.126953 C 35.660415,30.126953 36.209646,29.608969 36.209646,28.779297 L 36.209646,24.982422 C 36.209646,24.982422 23.209646,24.982422 23.209646,24.982422 z " id="path4880" sodipodi:nodetypes="ccccccc"/>
+ <path sodipodi:nodetypes="ccccccc" id="rect3119" d="M 35.584646,25.03125 L 35.584646,26.948131 C 35.584646,27.357741 35.208334,27.6875 34.740896,27.6875 L 24.678396,27.6875 C 24.210959,27.6875 23.834646,27.357741 23.834646,26.948131 L 23.834646,25.03125 C 23.834646,25.03125 35.584646,25.03125 35.584646,25.03125 z " style="color:#000000;fill:url(#linearGradient2446);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"/>
+ <path sodipodi:nodetypes="cscccccccccccccsccsccsccsccsc" id="path4918" d="M 21.803396,17.875 C 21.803396,17.875 22.959646,18.59375 23.240896,19.65625 C 23.522146,20.71875 23.678396,21.75 23.678396,21.75 L 24.459646,20.03125 L 25.334646,20.875 L 25.647146,19.5 L 27.522146,20 L 27.022146,18.96875 L 29.022146,19.90625 L 28.959646,19.21875 L 29.803396,19.96875 L 30.490896,19.34375 L 31.990896,20 L 32.865896,19.15625 L 34.115896,19.96875 C 34.115896,19.96875 33.897146,19.40625 34.022146,19.4375 C 34.147146,19.46875 35.240896,19.84375 35.240896,19.84375 L 35.522146,20.1875 C 35.522146,20.1875 35.331603,19.229934 34.897146,18.84375 C 34.053396,18.09375 32.865896,18.15625 32.865896,18.15625 L 32.740896,19.03125 C 32.740896,19.03125 31.709646,18.3125 30.834646,18.1875 C 29.959646,18.0625 29.084646,18.21875 29.084646,18.21875 L 28.897146,18.59375 C 28.897146,18.59375 27.803396,18.15625 26.834646,18.0625 C 25.865896,17.96875 24.615896,18 24.615896,18 L 24.553396,18.34375 C 24.553396,18.34375 23.647146,17.90625 23.240896,17.875 C 22.834646,17.84375 21.834646,17.90625 21.803396,17.875 z " style="opacity:1;color:#000000;fill:url(#linearGradient2448);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"/>
+ <path transform="matrix(0.888889,0.000000,0.000000,0.888889,3.647723,4.055556)" d="M 30.25 36.5 A 1.125 1.125 0 1 1 28,36.5 A 1.125 1.125 0 1 1 30.25 36.5 z" sodipodi:ry="1.125" sodipodi:rx="1.125" sodipodi:cy="36.5" sodipodi:cx="29.125" id="path4928" style="opacity:0.51461989;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" sodipodi:type="arc"/>
+ </g>
+ <path style="opacity:0.51461989;color:#000000;fill:url(#linearGradient2425);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" d="M 15.755226,9.396389 C 15.755226,9.396389 16.373944,13.727418 16.285556,15.362603 C 16.48443,12.313205 16.086682,9.5510687 16.086682,9.5510687 L 15.070216,8.4904085 L 15.755226,9.396389 z " id="path2410" sodipodi:nodetypes="ccccc"/>
+ </g>
+</svg>
\ No newline at end of file
=== added file 'data/media/slidewall_monitor.png'
Binary files data/media/slidewall_monitor.png 1970-01-01 00:00:00 +0000 and data/media/slidewall_monitor.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/media/soundwave'
=== added file 'data/media/soundwave/am.png'
Binary files data/media/soundwave/am.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/am.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/bg.jpg'
Binary files data/media/soundwave/bg.jpg 1970-01-01 00:00:00 +0000 and data/media/soundwave/bg.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/clock.ini'
--- data/media/soundwave/clock.ini 1970-01-01 00:00:00 +0000
+++ data/media/soundwave/clock.ini 2013-05-09 22:05:30 +0000
@@ -0,0 +1,19 @@
+[Settings]
+name=Sound Wave
+width=1440
+height=900
+author=Vlad Gerasimov
+email=vladstudio@xxxxxxxxx
+ampmenabled=1
+description=
+homepageURL=http://www.vladstudio.com
+downloadURL=http://www.vladstudio.com
+refreshhourinterval=60
+hourimages=24
+
+[Animation]
+
+[WallpaperClock]
+specVersion=1.0
+specampmenabled=1
+description=http://www.wallpaperclock.com/wcz/spec.php
\ No newline at end of file
=== added file 'data/media/soundwave/day1.png'
Binary files data/media/soundwave/day1.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day10.png'
Binary files data/media/soundwave/day10.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day11.png'
Binary files data/media/soundwave/day11.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day12.png'
Binary files data/media/soundwave/day12.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day13.png'
Binary files data/media/soundwave/day13.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day14.png'
Binary files data/media/soundwave/day14.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day15.png'
Binary files data/media/soundwave/day15.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day16.png'
Binary files data/media/soundwave/day16.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day17.png'
Binary files data/media/soundwave/day17.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day18.png'
Binary files data/media/soundwave/day18.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day19.png'
Binary files data/media/soundwave/day19.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day2.png'
Binary files data/media/soundwave/day2.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day20.png'
Binary files data/media/soundwave/day20.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day21.png'
Binary files data/media/soundwave/day21.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day22.png'
Binary files data/media/soundwave/day22.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day23.png'
Binary files data/media/soundwave/day23.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day24.png'
Binary files data/media/soundwave/day24.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day25.png'
Binary files data/media/soundwave/day25.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day26.png'
Binary files data/media/soundwave/day26.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day27.png'
Binary files data/media/soundwave/day27.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day28.png'
Binary files data/media/soundwave/day28.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day29.png'
Binary files data/media/soundwave/day29.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day3.png'
Binary files data/media/soundwave/day3.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day30.png'
Binary files data/media/soundwave/day30.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day31.png'
Binary files data/media/soundwave/day31.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day4.png'
Binary files data/media/soundwave/day4.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day5.png'
Binary files data/media/soundwave/day5.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day6.png'
Binary files data/media/soundwave/day6.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day7.png'
Binary files data/media/soundwave/day7.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day8.png'
Binary files data/media/soundwave/day8.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/day9.png'
Binary files data/media/soundwave/day9.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/day9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour0.png'
Binary files data/media/soundwave/hour0.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour1.png'
Binary files data/media/soundwave/hour1.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour10.png'
Binary files data/media/soundwave/hour10.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour11.png'
Binary files data/media/soundwave/hour11.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour12.png'
Binary files data/media/soundwave/hour12.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour13.png'
Binary files data/media/soundwave/hour13.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour14.png'
Binary files data/media/soundwave/hour14.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour15.png'
Binary files data/media/soundwave/hour15.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour16.png'
Binary files data/media/soundwave/hour16.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour17.png'
Binary files data/media/soundwave/hour17.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour18.png'
Binary files data/media/soundwave/hour18.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour19.png'
Binary files data/media/soundwave/hour19.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour2.png'
Binary files data/media/soundwave/hour2.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour20.png'
Binary files data/media/soundwave/hour20.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour21.png'
Binary files data/media/soundwave/hour21.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour22.png'
Binary files data/media/soundwave/hour22.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour23.png'
Binary files data/media/soundwave/hour23.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour3.png'
Binary files data/media/soundwave/hour3.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour4.png'
Binary files data/media/soundwave/hour4.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour5.png'
Binary files data/media/soundwave/hour5.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour6.png'
Binary files data/media/soundwave/hour6.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour7.png'
Binary files data/media/soundwave/hour7.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour8.png'
Binary files data/media/soundwave/hour8.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/hour9.png'
Binary files data/media/soundwave/hour9.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/hour9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute0.png'
Binary files data/media/soundwave/minute0.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute0.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute1.png'
Binary files data/media/soundwave/minute1.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute10.png'
Binary files data/media/soundwave/minute10.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute11.png'
Binary files data/media/soundwave/minute11.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute12.png'
Binary files data/media/soundwave/minute12.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute13.png'
Binary files data/media/soundwave/minute13.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute13.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute14.png'
Binary files data/media/soundwave/minute14.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute14.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute15.png'
Binary files data/media/soundwave/minute15.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute15.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute16.png'
Binary files data/media/soundwave/minute16.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute16.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute17.png'
Binary files data/media/soundwave/minute17.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute17.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute18.png'
Binary files data/media/soundwave/minute18.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute18.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute19.png'
Binary files data/media/soundwave/minute19.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute19.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute2.png'
Binary files data/media/soundwave/minute2.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute20.png'
Binary files data/media/soundwave/minute20.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute20.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute21.png'
Binary files data/media/soundwave/minute21.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute21.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute22.png'
Binary files data/media/soundwave/minute22.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute22.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute23.png'
Binary files data/media/soundwave/minute23.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute23.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute24.png'
Binary files data/media/soundwave/minute24.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute24.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute25.png'
Binary files data/media/soundwave/minute25.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute25.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute26.png'
Binary files data/media/soundwave/minute26.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute26.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute27.png'
Binary files data/media/soundwave/minute27.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute27.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute28.png'
Binary files data/media/soundwave/minute28.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute28.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute29.png'
Binary files data/media/soundwave/minute29.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute29.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute3.png'
Binary files data/media/soundwave/minute3.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute30.png'
Binary files data/media/soundwave/minute30.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute30.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute31.png'
Binary files data/media/soundwave/minute31.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute31.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute32.png'
Binary files data/media/soundwave/minute32.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute32.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute33.png'
Binary files data/media/soundwave/minute33.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute33.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute34.png'
Binary files data/media/soundwave/minute34.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute34.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute35.png'
Binary files data/media/soundwave/minute35.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute35.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute36.png'
Binary files data/media/soundwave/minute36.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute36.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute37.png'
Binary files data/media/soundwave/minute37.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute37.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute38.png'
Binary files data/media/soundwave/minute38.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute38.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute39.png'
Binary files data/media/soundwave/minute39.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute39.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute4.png'
Binary files data/media/soundwave/minute4.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute40.png'
Binary files data/media/soundwave/minute40.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute40.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute41.png'
Binary files data/media/soundwave/minute41.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute41.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute42.png'
Binary files data/media/soundwave/minute42.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute42.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute43.png'
Binary files data/media/soundwave/minute43.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute43.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute44.png'
Binary files data/media/soundwave/minute44.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute44.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute45.png'
Binary files data/media/soundwave/minute45.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute45.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute46.png'
Binary files data/media/soundwave/minute46.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute46.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute47.png'
Binary files data/media/soundwave/minute47.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute47.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute48.png'
Binary files data/media/soundwave/minute48.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute48.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute49.png'
Binary files data/media/soundwave/minute49.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute49.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute5.png'
Binary files data/media/soundwave/minute5.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute50.png'
Binary files data/media/soundwave/minute50.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute50.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute51.png'
Binary files data/media/soundwave/minute51.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute51.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute52.png'
Binary files data/media/soundwave/minute52.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute52.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute53.png'
Binary files data/media/soundwave/minute53.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute53.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute54.png'
Binary files data/media/soundwave/minute54.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute54.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute55.png'
Binary files data/media/soundwave/minute55.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute55.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute56.png'
Binary files data/media/soundwave/minute56.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute56.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute57.png'
Binary files data/media/soundwave/minute57.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute57.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute58.png'
Binary files data/media/soundwave/minute58.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute58.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute59.png'
Binary files data/media/soundwave/minute59.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute59.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute6.png'
Binary files data/media/soundwave/minute6.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute7.png'
Binary files data/media/soundwave/minute7.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute8.png'
Binary files data/media/soundwave/minute8.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/minute9.png'
Binary files data/media/soundwave/minute9.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/minute9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month1.png'
Binary files data/media/soundwave/month1.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month10.png'
Binary files data/media/soundwave/month10.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month10.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month11.png'
Binary files data/media/soundwave/month11.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month11.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month12.png'
Binary files data/media/soundwave/month12.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month12.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month2.png'
Binary files data/media/soundwave/month2.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month3.png'
Binary files data/media/soundwave/month3.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month4.png'
Binary files data/media/soundwave/month4.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month5.png'
Binary files data/media/soundwave/month5.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month6.png'
Binary files data/media/soundwave/month6.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month7.png'
Binary files data/media/soundwave/month7.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month7.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month8.png'
Binary files data/media/soundwave/month8.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month8.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/month9.png'
Binary files data/media/soundwave/month9.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/month9.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/pm.png'
Binary files data/media/soundwave/pm.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/pm.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/preview100x75.jpg'
Binary files data/media/soundwave/preview100x75.jpg 1970-01-01 00:00:00 +0000 and data/media/soundwave/preview100x75.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/preview200x150.jpg'
Binary files data/media/soundwave/preview200x150.jpg 1970-01-01 00:00:00 +0000 and data/media/soundwave/preview200x150.jpg 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday1.png'
Binary files data/media/soundwave/weekday1.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday1.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday2.png'
Binary files data/media/soundwave/weekday2.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday2.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday3.png'
Binary files data/media/soundwave/weekday3.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday3.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday4.png'
Binary files data/media/soundwave/weekday4.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday4.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday5.png'
Binary files data/media/soundwave/weekday5.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday5.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday6.png'
Binary files data/media/soundwave/weekday6.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday6.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/media/soundwave/weekday7.png'
Binary files data/media/soundwave/weekday7.png 1970-01-01 00:00:00 +0000 and data/media/soundwave/weekday7.png 2013-05-09 22:05:30 +0000 differ
=== added directory 'data/ui'
=== added file 'data/ui/AboutSlidewallDialog.ui'
--- data/ui/AboutSlidewallDialog.ui 1970-01-01 00:00:00 +0000
+++ data/ui/AboutSlidewallDialog.ui 2013-05-09 22:05:30 +0000
@@ -0,0 +1,57 @@
+<interface>
+ <!-- interface-requires about_slidewall_dialog 1.0 -->
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="AboutSlidewallDialog" id="about_slidewall_dialog">
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="border_width">5</property>
+ <property name="icon">../media/slidewall.png</property>
+ <property name="type_hint">normal</property>
+ <property name="program_name">Slidewall</property>
+ <property name="version">12.08</property>
+ <property name="copyright" translatable="yes">Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx></property>
+ <property name="website">https://launchpad.net/slidewall</property>
+ <property name="website_label" translatable="yes">Follow up my PPA</property>
+ <property name="license" translatable="yes"># Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+</property>
+ <property name="authors">Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx></property>
+ <property name="documenters">Faur Ioan-Aurel <fioan89@xxxxxxxxx></property>
+ <property name="logo">../media/slidewall.png</property>
+ <property name="license_type">gpl-3-0</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
\ No newline at end of file
=== added file 'data/ui/SlidewallWindow.ui'
--- data/ui/SlidewallWindow.ui 1970-01-01 00:00:00 +0000
+++ data/ui/SlidewallWindow.ui 2013-05-09 22:05:30 +0000
@@ -0,0 +1,873 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <!-- interface-requires slidewall_window 1.0 -->
+ <!-- interface-local-resource-path ../media -->
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">60</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment3">
+ <property name="upper">20</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-media-play</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixbuf">../media/slidewall.png</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-delete</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <object class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-open</property>
+ </object>
+ <object class="GtkImage" id="image8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-media-play</property>
+ </object>
+ <object class="GtkImage" id="img_next">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-go-forward</property>
+ </object>
+ <object class="GtkImage" id="img_prev">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-go-back</property>
+ </object>
+ <object class="GtkImage" id="img_quit">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-quit</property>
+ </object>
+ <object class="GtkImage" id="img_view">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-home</property>
+ </object>
+ <object class="SlidewallWindow" id="slidewall_window">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Slidewall</property>
+ <property name="resizable">False</property>
+ <property name="window_position">center</property>
+ <property name="default_width">399</property>
+ <property name="default_height">401</property>
+ <property name="icon">../media/slidewall.png</property>
+ <property name="opacity">0.99000000022351742</property>
+ <signal name="destroy" handler="on_destroy" swapped="no"/>
+ <signal name="destroy-event" handler="on_destroy" swapped="no"/>
+ <signal name="delete-event" handler="on_delete_event" swapped="no"/>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <signal name="delete-event" handler="on_bt_close_clicked" swapped="no"/>
+ <child>
+ <object class="GtkMenuItem" id="mnu_file">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="mnu_close">
+ <property name="label">gtk-close</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <accelerator key="w" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="mnu_help">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="helpMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="mnu_contents">
+ <property name="label" translatable="yes">Contents</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="image">image2</property>
+ <property name="use_stock">False</property>
+ <accelerator key="F1" signal="activate"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="mnu_about">
+ <property name="label">gtk-about</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="wall_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">15</property>
+ <property name="margin_bottom">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="ypad">2</property>
+ <property name="label" translatable="yes">Wall Mode</property>
+ <attributes>
+ <attribute name="font-desc" value="Sans Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="r_bt_slide">
+ <property name="label" translatable="yes">SlideShow Mode</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin_left">20</property>
+ <property name="use_action_appearance">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.55000001192092896</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">r_bt_live</property>
+ <signal name="toggled" handler="slide_togled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="r_bt_live">
+ <property name="label" translatable="yes">Live Wallpaper Mode</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin_left">20</property>
+ <property name="use_action_appearance">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">r_bt_slide</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="timing_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">15</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_timing">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Timing for Slideshow Mode</property>
+ <attributes>
+ <attribute name="font-desc" value="Sans Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">20</property>
+ <child>
+ <object class="GtkLabel" id="label_slideshow_timing">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">SlideShow Timing:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spiner_minutes">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <property name="invisible_char_set">True</property>
+ <property name="adjustment">adjustment3</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_minutes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"> minutes </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spiner_seconds">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <property name="invisible_char_set">True</property>
+ <property name="adjustment">adjustment2</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_seconds">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">seconds</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="misc_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">15</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Miscellaneous</property>
+ <attributes>
+ <attribute name="font-desc" value="Sans Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="check_tray">
+ <property name="label" translatable="yes">Minimize to system tray</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="check_notify">
+ <property name="label" translatable="yes">Notify me when wallpaper changes</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="check_autostart">
+ <property name="label" translatable="yes">Run Slidewall when Ubuntu is starting</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">2</property>
+ <property name="margin_top">25</property>
+ <property name="margin_bottom">5</property>
+ <property name="spacing">20</property>
+ <child>
+ <object class="GtkButton" id="bt_reset">
+ <property name="label" translatable="yes">Reset Preferences</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_bt_reset_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_save">
+ <property name="label" translatable="yes">Save Preferences</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_bt_save_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_quit">
+ <property name="label" translatable="yes">Quit SlideWall</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_bt_quit_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_close">
+ <property name="label" translatable="yes">Close to tray</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <signal name="clicked" handler="on_bt_close_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="yalign">0.50999999046325684</property>
+ <property name="ypad">7</property>
+ <property name="label" translatable="yes">Preferences</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFixed" id="fixed1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="margin_right">7</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="width_request">350</property>
+ <property name="height_request">485</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkIconView" id="wall_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="selection_mode">multiple</property>
+ <property name="reorderable">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="y">35</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="width_request">100</property>
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Wallpapers</property>
+ <attributes>
+ <attribute name="font-desc" value="Ubuntu Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="x">120</property>
+ <property name="y">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="width_request">100</property>
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Options</property>
+ <attributes>
+ <attribute name="font-desc" value="Ubuntu Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="x">391</property>
+ <property name="y">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_start">
+ <property name="label" translatable="yes"> Start</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Start Slideshow</property>
+ <property name="use_action_appearance">False</property>
+ <property name="image">image1</property>
+ <property name="xalign">0.50999999046325684</property>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">480</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_delete">
+ <property name="label" translatable="yes"> Delete</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="image">image3</property>
+ <property name="relief">half</property>
+ <signal name="clicked" handler="bt" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">430</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_select_files">
+ <property name="label" translatable="yes"> Load Imges</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="image">image4</property>
+ <property name="relief">half</property>
+ <signal name="clicked" handler="on_bt_select_files_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">380</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_select_folder">
+ <property name="label" translatable="yes"> Load Folder</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="image">image5</property>
+ <property name="relief">half</property>
+ <signal name="clicked" handler="on_bt_select_folder_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">330</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image6">
+ <property name="width_request">200</property>
+ <property name="height_request">180</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixbuf">../media/slidewall_monitor.png</property>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">35</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="cb_options">
+ <property name="width_request">140</property>
+ <property name="height_request">35</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">How the wallpaper will loo on your desktop</property>
+ <property name="wrap_width">1</property>
+ <property name="active">1</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <items>
+ <item translatable="yes">Zoom</item>
+ <item translatable="yes">Scaled</item>
+ <item translatable="yes">Centered</item>
+ <item translatable="yes">Spanned</item>
+ <item translatable="yes">Stretched</item>
+ <item translatable="yes">Wallpaper</item>
+ </items>
+ <signal name="changed" handler="on_cb_options_changed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">420</property>
+ <property name="y">230</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Slideshow</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFixed" id="fixed2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="margin_right">7</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="width_request">350</property>
+ <property name="height_request">485</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkIconView" id="live_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="item_orientation">horizontal</property>
+ <property name="reorderable">True</property>
+ <signal name="selection-changed" handler="on_live_view_clicked" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="y">35</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="width_request">100</property>
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Wallpapers</property>
+ <attributes>
+ <attribute name="font-desc" value="Ubuntu Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="x">120</property>
+ <property name="y">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="width_request">100</property>
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Info</property>
+ <attributes>
+ <attribute name="font-desc" value="Ubuntu Bold 10"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="x">391</property>
+ <property name="y">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_apply">
+ <property name="label">gtk-apply</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Start LiveWall</property>
+ <property name="tooltip_text" translatable="yes">Start LiveWall</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <property name="xalign">0.50999999046325684</property>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">480</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTextView" id="text_info">
+ <property name="width_request">200</property>
+ <property name="height_request">340</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word</property>
+ <property name="justification">center</property>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">35</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_add_clock">
+ <property name="label">gtk-add</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Import WallClock</property>
+ <property name="tooltip_text" translatable="yes">Import WallClock</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <property name="xalign">0.50999999046325684</property>
+ <signal name="clicked" handler="on_bt_add_clock_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">380</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="bt_del_clock">
+ <property name="label">gtk-delete</property>
+ <property name="use_action_appearance">False</property>
+ <property name="width_request">200</property>
+ <property name="height_request">36</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip_markup" translatable="yes">Delete WallClock</property>
+ <property name="tooltip_text" translatable="yes">Delete WallClock</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <property name="xalign">0.50999999046325684</property>
+ <signal name="clicked" handler="on_bt_del_clock_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="x">360</property>
+ <property name="y">430</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Live Wallpapers</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
=== added file 'data/ui/about_slidewall_dialog.xml'
--- data/ui/about_slidewall_dialog.xml 1970-01-01 00:00:00 +0000
+++ data/ui/about_slidewall_dialog.xml 2013-05-09 22:05:30 +0000
@@ -0,0 +1,9 @@
+<glade-catalog name="about_slidewall_dialog" domain="glade-3"
+ depends="gtk+" version="1.0">
+ <glade-widget-classes>
+ <glade-widget-class title="About Slidewall Dialog" name="AboutSlidewallDialog"
+ generic-name="AboutSlidewallDialog" parent="GtkAboutDialog"
+ icon-name="widget-gtk-about-dialog"/>
+ </glade-widget-classes>
+
+</glade-catalog>
=== added file 'data/ui/background.png'
Binary files data/ui/background.png 1970-01-01 00:00:00 +0000 and data/ui/background.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/ui/slidewall.png'
Binary files data/ui/slidewall.png 1970-01-01 00:00:00 +0000 and data/ui/slidewall.png 2013-05-09 22:05:30 +0000 differ
=== added file 'data/ui/slidewall_window.xml'
--- data/ui/slidewall_window.xml 1970-01-01 00:00:00 +0000
+++ data/ui/slidewall_window.xml 2013-05-09 22:05:30 +0000
@@ -0,0 +1,8 @@
+<glade-catalog name="slidewall_window" domain="glade-3"
+ depends="gtk+" version="1.0">
+ <glade-widget-classes>
+ <glade-widget-class title="Slidewall Window" name="SlidewallWindow"
+ generic-name="SlidewallWindow" parent="GtkWindow"
+ icon-name="widget-gtk-window"/>
+ </glade-widget-classes>
+</glade-catalog>
=== added directory 'debian'
=== added file 'debian/changelog'
--- debian/changelog 1970-01-01 00:00:00 +0000
+++ debian/changelog 2013-05-09 22:05:30 +0000
@@ -0,0 +1,24 @@
+slidewall (12.08) precise; urgency=low
+
+ * Bug fix for : #1033524 live earth wallpaper always used when the
+ app starts
+
+ -- fioan89@xxxxxxxxx <fioan89@xxxxxxxxx> Sat, 11 Aug 2012 19:44:17 +0300
+
+slidewall (12.07.18) precise; urgency=low
+
+ * New release.
+
+ -- fioan89@xxxxxxxxx <fioan89@xxxxxxxxx> Sun, 29 Jul 2012 15:33:55 +0300
+
+slidewall (12.07.17) precise; urgency=low
+
+ * A better working copy of slidewall with clock feature
+
+ -- fioan89@xxxxxxxxx <fioan89@xxxxxxxxx> Sun, 29 Jul 2012 15:32:48 +0300
+
+slidewall (12.07.16) precise; urgency=low
+
+ * Initial release.
+
+ -- Faur Ioan-Aurel <faur@BlueEyes> Sun, 29 Jul 2012 15:29:42 +0300
=== added file 'debian/compat'
--- debian/compat 1970-01-01 00:00:00 +0000
+++ debian/compat 2013-05-09 22:05:30 +0000
@@ -0,0 +1,1 @@
+8
=== added file 'debian/control'
--- debian/control 1970-01-01 00:00:00 +0000
+++ debian/control 2013-05-09 22:05:30 +0000
@@ -0,0 +1,25 @@
+Source: slidewall
+Section: python
+Priority: extra
+Build-Depends: debhelper (>= 8), libglib2.0-bin, python (>= 2.6.6-3~),
+ python-distutils-extra (>= 2.10)
+Maintainer: fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+Standards-Version: 3.9.3
+X-Python-Version: >= 2.6
+
+Package: slidewall
+Architecture: all
+Depends: ${misc:Depends},
+ ${python:Depends},
+ gir1.2-notify-0.7,
+ gir1.2-gtk-3.0,
+ python-numpy,
+ gir1.2-glib-2.0,
+ gir1.2-gdkpixbuf-2.0,
+ gir1.2-appindicator3-0.1,
+ gir1.2-launchpad-integration-3.0,
+ yelp
+Description: Let Slidewall to change your wallpapers.
+ Slidwall is an wallpaper changer for Unity desktop.Created with Unity in
+ mind Slidewall is fun,simple and quite fast.With great features it will
+ be a pleasure to use this app.
=== added file 'debian/copyright'
--- debian/copyright 1970-01-01 00:00:00 +0000
+++ debian/copyright 2013-05-09 22:05:30 +0000
@@ -0,0 +1,18 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: slidewall
+Upstream-Contact: fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+Source: https://launchpad.net/slidewall
+
+Files: *
+Copyright: (C)
+Copyright: (C) != 1:
+Copyright: (C) 2006 Johann C. Rocholl <johann@xxxxxxxxxxxxxxxx>
+Copyright: (C) 2006 Nicko van Someren <nicko@xxxxxxxxx>
+Copyright: (C) 2009 David Jones <drj@xxxxxxxxx>
+Copyright: (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+Copyright: (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+Copyright: (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx></property>
+Copyright: (C) == 3 and
+License: GPL-3
+ The full text of the GPL is distributed in
+ /usr/share/common-licenses/GPL-3 on Debian systems.
=== added file 'debian/rules'
--- debian/rules 1970-01-01 00:00:00 +0000
+++ debian/rules 2013-05-09 22:05:30 +0000
@@ -0,0 +1,32 @@
+#!/usr/bin/make -f
+%:
+ifneq ($(shell dh -l | grep -xF translations),)
+ dh $@ --with python2,translations
+else
+ dh $@ --with python2
+endif
+
+override_dh_auto_install:
+ dh_auto_install -- --install-scripts=/opt/extras.ubuntu.com/slidewall/bin --install-data=/opt/extras.ubuntu.com/slidewall --install-lib=/opt/extras.ubuntu.com/slidewall
+
+override_dh_python2:
+ dh_python2 /opt/extras.ubuntu.com/slidewall
+
+
+override_dh_install:
+ dh_install
+ mkdir -p debian/slidewall/opt/extras.ubuntu.com/slidewall/bin
+ if [ -x debian/slidewall/opt/extras.ubuntu.com/slidewall/slidewall/slidewall ]; then mv debian/slidewall/opt/extras.ubuntu.com/slidewall/slidewall/slidewall debian/slidewall/opt/extras.ubuntu.com/slidewall/bin; fi
+ if [ -f debian/slidewall/opt/extras.ubuntu.com/slidewall/share/applications/slidewall.desktop ]; then \
+ mkdir -p debian/slidewall/usr/share/applications; \
+ mv debian/slidewall/opt/extras.ubuntu.com/slidewall/share/applications/slidewall.desktop debian/slidewall/usr/share/applications/extras-slidewall.desktop; \
+ rmdir --ignore-fail-on-non-empty debian/slidewall/opt/extras.ubuntu.com/slidewall/share/applications; \
+ sed -i 's|Exec=[^ ]*|Exec=/opt/extras.ubuntu.com/slidewall/bin/slidewall|' debian/slidewall/usr/share/applications/extras-slidewall.desktop; \
+ sed -i 's|Icon=/usr/|Icon=/opt/extras.ubuntu.com/slidewall/|' debian/slidewall/usr/share/applications/extras-slidewall.desktop; \
+ fi
+ grep -RlZ 'import gettext' debian/slidewall/* | xargs -0 -r sed -i 's|\(import\) gettext$$|\1 locale|'
+ grep -RlZ 'from gettext import gettext as _' debian/slidewall/* | xargs -0 -r sed -i 's|from gettext \(import gettext as _\)|from locale \1|'
+ grep -RlZ "gettext.textdomain('slidewall')" debian/slidewall/* | xargs -0 -r sed -i "s|gettext\(\.textdomain('slidewall')\)|locale\.bindtextdomain('slidewall', '/opt/extras.ubuntu.com/slidewall/share/locale')\nlocale\1|"
+ sed -i "s|__slidewall_data_directory__ =.*|__slidewall_data_directory__ = '/opt/extras.ubuntu.com/slidewall/share/slidewall/'|" debian/slidewall/opt/extras.ubuntu.com/slidewall/slidewall*/slidewallconfig.py
+ sed -i 's| sys.path.insert(0, opt_path)|\0\n os.putenv("XDG_DATA_DIRS", "%s:%s" % ("/opt/extras.ubuntu.com/slidewall/share/", os.getenv("XDG_DATA_DIRS", "")))|' debian/slidewall/opt/extras.ubuntu.com/slidewall/bin/slidewall
+ if [ -d debian/slidewall/opt/extras.ubuntu.com/slidewall/share/glib-2.0/schemas ]; then glib-compile-schemas debian/slidewall/opt/extras.ubuntu.com/slidewall/share/glib-2.0/schemas; fi
\ No newline at end of file
=== added directory 'help'
=== added directory 'help/C'
=== added directory 'help/C/figures'
=== added file 'help/C/figures/icon.png'
Binary files help/C/figures/icon.png 1970-01-01 00:00:00 +0000 and help/C/figures/icon.png 2013-05-09 22:05:30 +0000 differ
=== added file 'help/C/index.page'
--- help/C/index.page 1970-01-01 00:00:00 +0000
+++ help/C/index.page 2013-05-09 22:05:30 +0000
@@ -0,0 +1,34 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ type="guide"
+ id="index">
+
+<info>
+ <!-- This shows in the title bar so does not show [icon] -->
+ <title type="text">Slidewall</title>
+ <desc>The <app>Slidewall</app> help.</desc>
+ <credit type="author">
+ <name>Faur Ioan-Aurel</name>
+ <email>fioan89@xxxxxxxxx</email>
+ <years>2012</years>
+ </credit>
+ <license href="http://creativecommons.org/licenses/by-sa/3.0/">
+ <p>Creative Commons Attribution-Share Alike 3.0 Unported License</p>
+ </license>
+</info>
+
+<title>
+<!-- This shows on the page in title font -->
+<!-- the icon only shows when installed -->
+<media type="image" mime="image/png" src="figures/icon.png">[icon]</media>
+<app>Slidewall</app> Help
+</title>
+
+<p>Slidwall is a wallpaper changer for Unity desktop.The main goal is to eat very few resources and to be fun.Check it out,you will not be dissappointed!</p>
+
+<!-- This is the visible index -->
+<section id="contents" style="2column">
+<!-- other pages needs to have a link to index#contents for this to work -->
+<title>Contents</title>
+</section>
+
+</page>
=== added file 'help/C/preferences.page'
--- help/C/preferences.page 1970-01-01 00:00:00 +0000
+++ help/C/preferences.page 2013-05-09 22:05:30 +0000
@@ -0,0 +1,27 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ type="topic"
+ id="Preferences">
+
+<info>
+ <link type="guide" xref="index#contents"/>
+ <credit type="author">
+ <name>Faur Ioan-Aurel</name>
+ <email>fioan89@xxxxxxxxx</email>
+ <years>2012</years>
+ </credit>
+ <desc>A simple way to configure Slidewall</desc>
+</info>
+
+<title>Preferences</title>
+<p>In this mode you can select if you want a wallpaper slideshow or you will use the Live feature. </p>
+<p>
+In Timing for SlideShow Mode you will set the period after which the background will change.
+</p>
+<p>
+You can also enable notification or minimize to tray.
+</p>
+
+<p>
+You dont need to use Save Preferences button.The settings will be saved automatically.
+</p>
+</page>
=== added file 'help/C/topic1.page'
--- help/C/topic1.page 1970-01-01 00:00:00 +0000
+++ help/C/topic1.page 2013-05-09 22:05:30 +0000
@@ -0,0 +1,24 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ type="topic"
+ id="Slideshow">
+
+<info>
+ <link type="guide" xref="index#contents"/>
+ <credit type="author">
+ <name>Faur Ioan-Aurel</name>
+ <email>fioan89@xxxxxxxxx</email>
+ <years>2012</years>
+ </credit>
+ <desc>Check out the Slideshow feature</desc>
+</info>
+
+<title>Slideshow Mode</title>
+<p>In this mode you can add individual wallpapers or you can import an entire folder of pictures.</p>
+<p>
+Select how you want your wallpaper to look from top right Option panel.After that just hit start and your background will start to change with the timing you set in the Preferences tab.
+</p>
+<p>
+Your wallpapers will be remembered when you start the application.Please take note that if you hit the Apply button from Live Wallpapers,this mode will stop working.
+</p>
+
+</page>
=== added file 'help/C/topic2.page'
--- help/C/topic2.page 1970-01-01 00:00:00 +0000
+++ help/C/topic2.page 2013-05-09 22:05:30 +0000
@@ -0,0 +1,24 @@
+<page xmlns="http://projectmallard.org/1.0/"
+ type="topic"
+ id="Live">
+
+<info>
+ <link type="guide" xref="index#contents"/>
+ <credit type="author">
+ <name>Faur Ioan-Aurel</name>
+ <email>fioan89@xxxxxxxxx</email>
+ <years>2012</years>
+ </credit>
+ <desc>Check out the Live feature</desc>
+</info>
+
+<title>Live Mode</title>
+<p>In this mode you can use live images from the internet.</p>
+<p>
+Right now you can use the sunlight map ,wich will change every 20 minutes,or you can try the New Wallbase or Random Wallbase.The last two options will download images from the wallbase.cc.
+</p>
+<p>
+Please keep in mind that the last two options will take a while at first selection.That is because Slidewall must parse the wallbase.cc webpage to get your wallpapers.I will try to talk with the guys from the wallbase.cc and maybe we will resolve this issue by writing an API that will let developers to write better and faster code.
+</p>
+
+</page>
=== added directory 'po'
=== added file 'po/slidewall.pot'
--- po/slidewall.pot 1970-01-01 00:00:00 +0000
+++ po/slidewall.pot 2013-05-09 22:05:30 +0000
@@ -0,0 +1,211 @@
+# 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 <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-07-29 15:29+0300\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/ui/AboutSlidewallDialog.ui.h:1
+msgid "Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>"
+msgstr ""
+
+#: ../data/ui/AboutSlidewallDialog.ui.h:2
+msgid "Follow up my PPA"
+msgstr ""
+
+#: ../data/ui/AboutSlidewallDialog.ui.h:3
+msgid ""
+"# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>\n"
+"# This program is free software: you can redistribute it and/or modify it \n"
+"# under the terms of the GNU General Public License version 3, as "
+"published \n"
+"# by the Free Software Foundation.\n"
+"# \n"
+"# This program is distributed in the hope that it will be useful, but \n"
+"# WITHOUT ANY WARRANTY; without even the implied warranties of \n"
+"# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR \n"
+"# PURPOSE. See the GNU General Public License for more details.\n"
+"# \n"
+"# You should have received a copy of the GNU General Public License along \n"
+"# with this program. If not, see <http://www.gnu.org/licenses/>.\n"
+msgstr ""
+
+#: ../slidewall.desktop.in.h:1 ../data/ui/SlidewallWindow.ui.h:1
+msgid "Slidewall"
+msgstr ""
+
+#: ../slidewall.desktop.in.h:2
+msgid "Slidewall application"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:2
+msgid "_File"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:3
+msgid "_Help"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:4
+msgid "Contents"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:5
+msgid "Wall Mode"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:6
+msgid "SlideShow Mode"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:7
+msgid "Live Wallpaper Mode"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:8
+msgid "Timing for Slideshow Mode"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:9
+msgid "SlideShow Timing:"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:10
+msgid " minutes "
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:11
+msgid "seconds"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:12
+msgid "Miscellaneous"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:13
+msgid "Minimize to system tray"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:14
+msgid "Notify me when wallpaper changes"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:15
+msgid "Run Slidewall when Ubuntu is starting"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:16
+msgid "Reset Preferences"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:17
+msgid "Save Preferences"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:18
+msgid "Quit SlideWall"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:19
+msgid "Close to tray"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:20
+msgid "Preferences"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:21
+msgid "Wallpapers"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:22
+msgid "Options"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:23
+msgid " Start"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:24
+msgid "Start Slideshow"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:25
+msgid " Delete"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:26
+msgid " Load Imges"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:27
+msgid " Load Folder"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:28
+msgid "How the wallpaper will loo on your desktop"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:29
+msgid "Zoom"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:30
+msgid "Scaled"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:31
+msgid "Centered"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:32
+msgid "Spanned"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:33
+msgid "Stretched"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:34
+msgid "Wallpaper"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:35
+msgid "Slideshow"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:36
+msgid "Info"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:37
+msgid "Start LiveWall"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:38
+msgid "Import WallClock"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:39
+msgid "Delete WallClock"
+msgstr ""
+
+#: ../data/ui/SlidewallWindow.ui.h:40
+msgid "Live Wallpapers"
+msgstr ""
+
+#: ../slidewall/__init__.py:34
+msgid "Show debug messages (-vv debugs slidewall_lib also)"
+msgstr ""
=== added file 'setup.py'
--- setup.py 1970-01-01 00:00:00 +0000
+++ setup.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+###################### DO NOT TOUCH THIS (HEAD TO THE SECOND PART) ######################
+
+import os
+import sys
+
+try:
+ import DistUtilsExtra.auto
+except ImportError:
+ print >> sys.stderr, 'To build slidewall you need https://launchpad.net/python-distutils-extra'
+ sys.exit(1)
+assert DistUtilsExtra.auto.__version__ >= '2.18', 'needs DistUtilsExtra.auto >= 2.18'
+
+def update_config(values = {}):
+
+ oldvalues = {}
+ try:
+ fin = file('slidewall_lib/slidewallconfig.py', 'r')
+ fout = file(fin.name + '.new', 'w')
+
+ for line in fin:
+ fields = line.split(' = ') # Separate variable from value
+ if fields[0] in values:
+ oldvalues[fields[0]] = fields[1].strip()
+ line = "%s = %s\n" % (fields[0], values[fields[0]])
+ fout.write(line)
+
+ fout.flush()
+ fout.close()
+ fin.close()
+ os.rename(fout.name, fin.name)
+ except (OSError, IOError), e:
+ print ("ERROR: Can't find slidewall_lib/slidewallconfig.py")
+ sys.exit(1)
+ return oldvalues
+
+
+def update_desktop_file(datadir):
+
+ try:
+ fin = file('slidewall.desktop.in', 'r')
+ fout = file(fin.name + '.new', 'w')
+
+ for line in fin:
+ if 'Icon=' in line:
+ line = "Icon=%s\n" % (datadir + 'media/slidewall.svg')
+ fout.write(line)
+ fout.flush()
+ fout.close()
+ fin.close()
+ os.rename(fout.name, fin.name)
+ except (OSError, IOError), e:
+ print ("ERROR: Can't find slidewall.desktop.in")
+ sys.exit(1)
+
+
+class InstallAndUpdateDataDirectory(DistUtilsExtra.auto.install_auto):
+ def run(self):
+ values = {'__slidewall_data_directory__': "'%s'" % (self.prefix + '/share/slidewall/'),
+ '__version__': "'%s'" % self.distribution.get_version()}
+ previous_values = update_config(values)
+ update_desktop_file(self.prefix + '/share/slidewall/')
+ DistUtilsExtra.auto.install_auto.run(self)
+ update_config(previous_values)
+
+
+
+##################################################################################
+###################### YOU SHOULD MODIFY ONLY WHAT IS BELOW ######################
+##################################################################################
+
+DistUtilsExtra.auto.setup(
+ name='slidewall',
+ version='12.08',
+ license='GPL-3',
+ author='fioan89@xxxxxxxxx',
+ author_email='fioan89@xxxxxxxxx',
+ description='Let Slidewall to change your wallpapers.',
+ long_description='Slidwall is an wallpaper changer for Unity desktop.Created with Unity in mind Slidewall is fun,simple and quite fast.With great features it will be a pleasure to use this app.',
+ url='https://launchpad.net/slidewall',
+ cmdclass={'install': InstallAndUpdateDataDirectory}
+ )
+
=== added directory 'slidewall'
=== added file 'slidewall.desktop.in'
--- slidewall.desktop.in 1970-01-01 00:00:00 +0000
+++ slidewall.desktop.in 2013-05-09 22:05:30 +0000
@@ -0,0 +1,8 @@
+[Desktop Entry]
+_Name=Slidewall
+_Comment=Slidewall application
+Categories=GNOME;Utility;
+Exec=slidewall
+Icon=/usr/share/slidewall/media/slidewall.svg
+Terminal=false
+Type=Application
=== added file 'slidewall/AboutSlidewallDialog.py'
--- slidewall/AboutSlidewallDialog.py 1970-01-01 00:00:00 +0000
+++ slidewall/AboutSlidewallDialog.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,35 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+import logging
+logger = logging.getLogger('slidewall')
+
+from slidewall_lib.AboutDialog import AboutDialog
+
+# See slidewall_lib.AboutDialog.py for more details about how this class works.
+class AboutSlidewallDialog(AboutDialog):
+ __gtype_name__ = "AboutSlidewallDialog"
+
+ def finish_initializing(self, builder): # pylint: disable=E1002
+ """Set up the about dialog"""
+ super(AboutSlidewallDialog, self).finish_initializing(builder)
+
+ # Code for other initialization actions should be added here.
+
=== added file 'slidewall/SlidewallWindow.py'
--- slidewall/SlidewallWindow.py 1970-01-01 00:00:00 +0000
+++ slidewall/SlidewallWindow.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,40 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+from gi.repository import Gtk # pylint: disable=E0611
+import logging
+logger = logging.getLogger('slidewall')
+
+from slidewall_lib import Window
+from slidewall.AboutSlidewallDialog import AboutSlidewallDialog
+
+# See slidewall_lib.Window.py for more details about how this class works
+class SlidewallWindow(Window):
+ __gtype_name__ = "SlidewallWindow"
+
+ def finish_initializing(self, builder): # pylint: disable=E1002
+ """Set up the main window"""
+ super(SlidewallWindow, self).finish_initializing(builder)
+
+ self.AboutDialog = AboutSlidewallDialog
+ # Code for other initialization actions should be added here.
+
+
+
=== added file 'slidewall/__init__.py'
--- slidewall/__init__.py 1970-01-01 00:00:00 +0000
+++ slidewall/__init__.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,46 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import optparse
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+from gi.repository import Gtk # pylint: disable=E0611
+
+from slidewall import SlidewallWindow
+
+from slidewall_lib import set_up_logging, get_version
+
+def parse_options():
+ """Support for command line options"""
+ parser = optparse.OptionParser(version="%%prog %s" % get_version())
+ parser.add_option(
+ "-v", "--verbose", action="count", dest="verbose",
+ help=_("Show debug messages (-vv debugs slidewall_lib also)"))
+ (options, args) = parser.parse_args()
+
+ set_up_logging(options)
+
+def main():
+ 'constructor for your class instances'
+ parse_options()
+
+ # Run the application.
+ window = SlidewallWindow.SlidewallWindow()
+ window.show()
+ Gtk.main()
=== added directory 'slidewall_engine'
=== added file 'slidewall_engine/ConfEngine.py'
--- slidewall_engine/ConfEngine.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/ConfEngine.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,122 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+import os
+import logging
+import shelve
+class ConfigEngine:
+ '''This class is will help to load/store
+ user preferences'''
+
+ def __init__(self):
+ self.home_dir = os.environ['HOME']
+ self.share_dir = '.local/share'
+ self.app_dir = 'slidewall'
+ self.config_dir = 'config'
+ self.slide_dir = 'slideshow'
+ self.live_dir = 'live'
+ self.conf_file = "slidewall"
+ self.logger = logging.getLogger('slidewall_engine')
+ #check if slidewall_dir exist if not then create it
+ self.slidewall_dir = self.home_dir + '/' + self.share_dir + '/' + self.app_dir
+ self.make_dir(self.slidewall_dir)
+ #check if config folder exist else create it
+ self.slidewall_config_dir = self.slidewall_dir + '/' + self.config_dir
+ self.make_dir(self.slidewall_config_dir)
+ #check if slideshow folder exist else create it
+ self.slidewall_slide_dir = self.slidewall_dir + '/' + self.slide_dir
+ self.make_dir(self.slidewall_slide_dir)
+ #check if live folder exist else create it
+ self.slidewall_live_dir = self.slidewall_dir + '/' + self.live_dir
+ self.make_dir(self.slidewall_live_dir)
+ #check if slidewall.conf exist
+ self.slidewall_conf_file = self.slidewall_config_dir + '/' + self.conf_file
+ self.slidemode_conf_file = self.slidewall_config_dir + '/slidemode'
+ self.livemode_conf_file = self.slidewall_config_dir + '/livemode'
+ #self.make_file(self.slidewall_conf_file)
+
+ self.slidewall_data = self.find_data_folder()
+
+ def make_dir(self,folder):
+ '''This method check for the specified folder
+ and if it not exist than create it'''
+ if not os.path.exists(folder):
+ os.mkdir(folder)
+ self.logger.debug('Creating dir:' + folder)
+
+ def make_file(self,conf_file):
+ '''This method check if a file exist and if not it will create it'''
+ print('make_file:' + conf_file)
+ if not (os.path.exists(conf_file) and os.path.isfile(conf_file)):
+ fo = open(conf_file, "w")
+ fo.close()
+ self.logger.debug('Creating file:' +conf_file )
+
+ def write_config(self,config_dict):
+ '''This method will write a dictionary in a shelve file
+ '''
+ conf_file = shelve.open(self.slidewall_conf_file)
+ for key, value in config_dict.items():
+ conf_file[key]=value
+ conf_file.close()
+ def write_config_in_file(self,config_dict,shelve_path):
+ '''This method will write a dictionary in specified shelve file
+ '''
+ #print 'write_config_in_file::'
+ #print config_dict
+ #remove the old shelve
+ if os.path.exists(shelve_path):
+ os.remove(shelve_path)
+ #print 'write_config_in_file removed::' + shelve_path
+ conf_file = shelve.open(shelve_path)
+ for key, value in config_dict.items():
+ conf_file[key]=value
+ conf_file.close()
+
+ def read_config(self,config_dict):
+ '''This method will read and return a dictionary stored in shelve file'''
+ if(os.path.exists(config_dict)):
+ data=shelve.open(config_dict)
+ return data
+ else:
+ data={}
+ return data
+
+
+ def print_dict(self,data):
+ '''Just for debugging purpose.It will print out a dictionary'''
+ print("dictionary...")
+ for key,value in data.items():
+ print(key + ":" + str(value) + "\n")
+
+ def print_shelve(self,shelve_file):
+ '''Just for debugging purpose.It will print out a shelve'''
+ data = shelve.open(shelve_file)
+ print("shelve...")
+ for key,value in data.items():
+ print(key + ":" + str(value) + "\n")
+
+ def find_data_folder(self):
+ if(os.path.exists('/opt/extras.ubuntu.com/slidewall/share/')):
+ return '/opt/extras.ubuntu.com/slidewall/share/slidewall'
+ elif(os.path.exists('/usr/share/slidewall/')):
+ return '/usr/share/slidewall'
+ elif(os.path.exists('/usr/local/share/slidewall')):
+ return '/usr/share/local/share/slidewall'
+ elif(os.path.exists(os.getcwd() + '/data')):
+ return os.getcwd() + '/data'
+ else:
+ return ''
+
=== added file 'slidewall_engine/NotifyEngine.py'
--- slidewall_engine/NotifyEngine.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/NotifyEngine.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,24 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+from gi.repository import Notify
+
+class NotifyServer:
+ def __init__(self,app_name=''):
+ Notify.init(app_name)
+
+ def wall_notify(self,app_name='',message='',icon_path=''):
+ notify = Notify.Notification.new(app_name,message,icon_path)
+ notify.show()
=== added file 'slidewall_engine/SlideWallEngine.py'
--- slidewall_engine/SlideWallEngine.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/SlideWallEngine.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,66 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+from gi.repository import Gio
+
+class WallEngine:
+ """
+ Allow you to set wallpaper for the unity desktop
+ """
+ #path in gsettings registry for background
+ __background_path = "org.gnome.desktop.background"
+
+ def __init__(self):
+ self.settings = Gio.Settings.new(self.__background_path)
+
+ def get_wallpaper(self):
+ """
+ Return the path of the current wallpaper
+ """
+ value = self.settings.get_string("picture-uri")
+ return value
+
+ def get_picture_options(self):
+ """
+ Return how the background wallpaper is rendered.
+ Values : none,wallpaper,centered,scaled,
+ stretched,zoom,spanned
+ """
+ value = self.settings.get_string("picture-options")
+ return value
+
+ def set_wallpaper(self,image_uri=""):
+ """
+ Set a wallpaper for the background.The parameter
+ is uri so it should be like:
+ file:///home/user/Picture/some_picture.png
+ """
+ if image_uri.find("file:///"):
+ raise Exception('Path ' +image_uri + ' does not follow this format: file:///path_to_image')
+ else:
+ self.settings.set_string("picture-uri",image_uri)
+
+ def set_picture_options(self,option="stretch"):
+ """
+ Set how the background wallpaper is rendered.
+ Values : none,wallpaper,centered,scaled,
+ stretched,zoom,spanned
+ """
+ if option not in ["none","wallpaper","centered","scaled","stretched","zoom","spanned"]:
+ raise Exception("Option " + option +" is not in this list:none,wallpaper,centered,scaled,stretched,zoom,spanned")
+ else:
+ self.settings.set_string("picture-options",option)
+
+
=== added file 'slidewall_engine/__init__.py'
=== added file 'slidewall_engine/copythread.py'
--- slidewall_engine/copythread.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/copythread.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,24 @@
+
+import threading
+import os
+from shutil import copytree
+from slidewall_engine import ConfEngine
+
+class CopyThread ( threading.Thread ):
+ def __init__(self, parent):
+ self.parent = parent
+ threading.Thread.__init__(self)
+
+
+ def run ( self ):
+ self.config_engine = ConfEngine.ConfigEngine()
+ if(not os.path.isdir(self.config_engine.slidewall_live_dir + '/lcd_blue')):
+ copytree(self.config_engine.find_data_folder() + '/media/lcd_blue',self.config_engine.slidewall_live_dir + '/lcd_blue')
+ if(not os.path.isdir(self.config_engine.slidewall_live_dir + '/goldflame')):
+ copytree(self.config_engine.find_data_folder() + '/media/goldflame',self.config_engine.slidewall_live_dir + '/goldflame')
+ if(not os.path.isdir(self.config_engine.slidewall_live_dir + '/soundwave')):
+ copytree(self.config_engine.find_data_folder() + '/media/soundwave',self.config_engine.slidewall_live_dir + '/soundwave')
+ if(not os.path.isdir(self.config_engine.slidewall_live_dir + '/radarblue')):
+ copytree(self.config_engine.find_data_folder() + '/media/radarblue',self.config_engine.slidewall_live_dir + '/radarblue')
+ #update slidewall
+ self.parent.load_livemode_wall()
=== added file 'slidewall_engine/liveengine.py'
--- slidewall_engine/liveengine.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/liveengine.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,95 @@
+import os
+import logging
+from shutil import copytree
+from shutil import rmtree
+from gi.repository import Gtk,GdkPixbuf,GObject
+
+logger = logging.getLogger('slidewall_lib')
+
+class LiveEngine():
+ def __init__(self,parent = None):
+ self.parent = parent
+ if(not os.path.isdir(self.parent.config_engine.slidewall_live_dir + '/lcd_blue')):
+ copytree(self.parent.config_engine.find_data_folder() + '/media/lcd_blue',self.parent.config_engine.slidewall_live_dir + '/lcd_blue')
+ if(not os.path.isdir(self.parent.config_engine.slidewall_live_dir + '/goldflame')):
+ copytree(self.parent.config_engine.find_data_folder() + '/media/goldflame',self.parent.config_engine.slidewall_live_dir + '/goldflame')
+ if(not os.path.isdir(self.parent.config_engine.slidewall_live_dir + '/soundwave')):
+ copytree(self.parent.config_engine.find_data_folder() + '/media/soundwave',self.parent.config_engine.slidewall_live_dir + '/soundwave')
+ if(not os.path.isdir(self.parent.config_engine.slidewall_live_dir + '/radarblue')):
+ copytree(self.parent.config_engine.find_data_folder() + '/media/radarblue',self.parent.config_engine.slidewall_live_dir + '/radarblue')
+
+
+ def load_livemode_wall(self):
+ '''Load default livewall's for slidewall at startup'''
+ sc = self.parent.config_engine.slidewall_data
+ print '\n\n\n\n\n\tLoading...\n\n\n'
+ #we must load the default ones and then search the local share folder for the wallclock's
+ self.storee={'live earth': sc + '/media/map.png','new wallbase': sc + '/media/new.png','random wallbase': sc + '/media/random.png'}
+ print str(self.storee) + ' \n\n\t with keys:' + str(self.storee.keys())
+ for image in self.storee.keys():
+ try:
+ print "Loading::" + self.storee[str(image)]
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(self.storee[image],100,100)
+ self.parent.liststore3.append([pixbuf,image])
+ except Exception:
+ logger.debug(image + ' is not a image type')
+
+ #load other clocks from loca share
+ path = self.parent.config_engine.slidewall_live_dir
+ lists = os.listdir(path)
+ print 'liveengine::lists of clocks' + str(lists)
+ for clock in lists:
+ if(os.path.isdir(path + '/' + clock)):
+ try:
+ #print "Loading::" + storee['clock lcd_blue']
+ image = 'clock ' + clock
+ self.storee[image] = path + '/' + clock
+ print "Loading::" + self.storee[image]
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(self.storee[image]+'/preview200x150.jpg',100,100);
+ self.parent.liststore3.append([pixbuf,image])
+ except Exception:
+ logger.debug(image + ' is not a image type')
+
+ self.parent.ui.live_view.set_model(self.parent.liststore3)
+ self.parent.ui.live_view.thaw_child_notify()
+ self.parent.ui.live_view.set_pixbuf_column(0)
+ self.parent.ui.live_view.set_text_column(1)
+
+ def remove_bin(self,widget,data=None):
+ '''Remove selected items from liveview and from storee.It will return true if the user is trying to remove
+ default bins.It will help if you want to notify him'''
+ #this one should be moved in on_bt_delete
+ if('timer_id' in vars(self.parent) or 'timer_id' in globals()) and(self.parent.ui.r_bt_live.get_active()):
+ GObject.source_remove(self.parent.timer_id)
+ self.parent.last_position = 'live earth'
+ self.parent.timer_id = -1
+ print('Removed timer id')
+ logger.debug('on_bt_delete_clicked::timer removed')
+
+ selects = self.parent.ui.live_view.get_selected_items()
+ for select in selects:
+ iterr = self.parent.liststore3.get_iter(select)
+ datas = self.parent.liststore3.get(iterr,0,1)
+ if(not datas[1] in ['live earth', 'new wallbase', 'random wallbase', 'clock radarblue', 'clock goldflame', 'clock soundwave']):
+ del self.storee[str(datas[1])]
+ self.parent.liststore3.remove(iterr)
+ #remove from local store
+ name = datas[1][6:]
+ path = self.parent.config_engine.slidewall_live_dir
+ fullpath = path + '/' + name
+ print("Going to remove " + fullpath)
+ rmtree(fullpath)
+ return False
+ else:
+ return True
+
+ def get_selected(self):
+ '''Return the text from livew_view'''
+
+ selects = self.parent.ui.live_view.get_selected_items()
+ for select in selects:
+ iterr = self.parent.liststore3.get_iter(select)
+ datas = self.parent.liststore3.get(iterr,0,1)
+ print 'liveengine::get_selected()::selected item:' + str(datas[1])
+ return datas[1]
+
=== added file 'slidewall_engine/png.py'
--- slidewall_engine/png.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/png.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,3800 @@
+#!/usr/bin/env python
+
+# $URL$
+# $Rev$
+
+# png.py - PNG encoder/decoder in pure Python
+#
+# Copyright (C) 2006 Johann C. Rocholl <johann@xxxxxxxxxxxxxxxx>
+# Portions Copyright (C) 2009 David Jones <drj@xxxxxxxxx>
+# And probably portions Copyright (C) 2006 Nicko van Someren <nicko@xxxxxxxxx>
+#
+# Original concept by Johann C. Rocholl.
+#
+# LICENSE (The MIT License)
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# Changelog (recent first):
+# 2009-03-11 David: interlaced bit depth < 8 (writing).
+# 2009-03-10 David: interlaced bit depth < 8 (reading).
+# 2009-03-04 David: Flat and Boxed pixel formats.
+# 2009-02-26 David: Palette support (writing).
+# 2009-02-23 David: Bit-depths < 8; better PNM support.
+# 2006-06-17 Nicko: Reworked into a class, faster interlacing.
+# 2006-06-17 Johann: Very simple prototype PNG decoder.
+# 2006-06-17 Nicko: Test suite with various image generators.
+# 2006-06-17 Nicko: Alpha-channel, grey-scale, 16-bit/plane support.
+# 2006-06-15 Johann: Scanline iterator interface for large input files.
+# 2006-06-09 Johann: Very simple prototype PNG encoder.
+
+# Incorporated into Bangai-O Development Tools by drj on 2009-02-11 from
+# http://trac.browsershots.org/browser/trunk/pypng/lib/png.py?rev=2885
+
+# Incorporated into pypng by drj on 2009-03-12 from
+# //depot/prj/bangaio/master/code/png.py#67
+
+
+"""
+Pure Python PNG Reader/Writer
+
+This Python module implements support for PNG images (see PNG
+specification at http://www.w3.org/TR/2003/REC-PNG-20031110/ ). It reads
+and writes PNG files with all allowable bit depths (1/2/4/8/16/24/32/48/64
+bits per pixel) and colour combinations: greyscale (1/2/4/8/16 bit); RGB,
+RGBA, LA (greyscale with alpha) with 8/16 bits per channel; colour mapped
+images (1/2/4/8 bit). Adam7 interlacing is supported for reading and
+writing. A number of optional chunks can be specified (when writing)
+and understood (when reading): ``tRNS``, ``bKGD``, ``gAMA``.
+
+For help, type ``import png; help(png)`` in your python interpreter.
+
+A good place to start is the :class:`Reader` and :class:`Writer` classes.
+
+Requires Python 2.3. Limited support is available for Python 2.2, but
+not everything works. Best with Python 2.4 and higher. Installation is
+trivial, but see the ``README.txt`` file (with the source distribution)
+for details.
+
+This file can also be used as a command-line utility to convert
+`Netpbm <http://netpbm.sourceforge.net/>`_ PNM files to PNG, and the reverse conversion from PNG to
+PNM. The interface is similar to that of the ``pnmtopng`` program from
+Netpbm. Type ``python png.py --help`` at the shell prompt
+for usage and a list of options.
+
+A note on spelling and terminology
+----------------------------------
+
+Generally British English spelling is used in the documentation. So
+that's "greyscale" and "colour". This not only matches the author's
+native language, it's also used by the PNG specification.
+
+The major colour models supported by PNG (and hence by PyPNG) are:
+greyscale, RGB, greyscale--alpha, RGB--alpha. These are sometimes
+referred to using the abbreviations: L, RGB, LA, RGBA. In this case
+each letter abbreviates a single channel: *L* is for Luminance or Luma or
+Lightness which is the channel used in greyscale images; *R*, *G*, *B* stand
+for Red, Green, Blue, the components of a colour image; *A* stands for
+Alpha, the opacity channel (used for transparency effects, but higher
+values are more opaque, so it makes sense to call it opacity).
+
+A note on formats
+-----------------
+
+When getting pixel data out of this module (reading) and presenting
+data to this module (writing) there are a number of ways the data could
+be represented as a Python value. Generally this module uses one of
+three formats called "flat row flat pixel", "boxed row flat pixel", and
+"boxed row boxed pixel". Basically the concern is whether each pixel
+and each row comes in its own little tuple (box), or not.
+
+Consider an image that is 3 pixels wide by 2 pixels high, and each pixel
+has RGB components:
+
+Boxed row flat pixel::
+
+ list([R,G,B, R,G,B, R,G,B],
+ [R,G,B, R,G,B, R,G,B])
+
+Each row appears as its own list, but the pixels are flattened so that
+three values for one pixel simply follow the three values for the previous
+pixel. This is the most common format used, because it provides a good
+compromise between space and convenience. PyPNG regards itself as
+at liberty to replace any sequence type with any sufficiently compatible
+other sequence type; in practice each row is an array (from the array
+module), and the outer list is sometimes an iterator rather than an
+explicit list (so that streaming is possible).
+
+Flat row flat pixel::
+
+ [R,G,B, R,G,B, R,G,B,
+ R,G,B, R,G,B, R,G,B]
+
+The entire image is one single giant sequence of colour values.
+Generally an array will be used (to save space), not a list.
+
+Boxed row boxed pixel::
+
+ list([ (R,G,B), (R,G,B), (R,G,B) ],
+ [ (R,G,B), (R,G,B), (R,G,B) ])
+
+Each row appears in its own list, but each pixel also appears in its own
+tuple. A serious memory burn in Python.
+
+In all cases the top row comes first, and for each row the pixels are
+ordered from left-to-right. Within a pixel the values appear in the
+order, R-G-B-A (or L-A for greyscale--alpha).
+
+There is a fourth format, mentioned because it is used internally,
+is close to what lies inside a PNG file itself, and has some support
+from the public API. This format is called packed. When packed,
+each row is a sequence of bytes (integers from 0 to 255), just as
+it is before PNG scanline filtering is applied. When the bit depth
+is 8 this is essentially the same as boxed row flat pixel; when the
+bit depth is less than 8, several pixels are packed into each byte;
+when the bit depth is 16 (the only value more than 8 that is supported
+by the PNG image format) each pixel value is decomposed into 2 bytes
+(and `packed` is a misnomer). This format is used by the
+:meth:`Writer.write_packed` method. It isn't usually a convenient
+format, but may be just right if the source data for the PNG image
+comes from something that uses a similar format (for example, 1-bit
+BMPs, or another PNG file).
+
+And now, my famous members
+--------------------------
+"""
+
+# http://www.python.org/doc/2.2.3/whatsnew/node5.html
+from __future__ import generators
+
+__version__ = "$URL$ $Rev$"
+
+from array import array
+try: # See :pyver:old
+ import itertools
+except:
+ pass
+import math
+# http://www.python.org/doc/2.4.4/lib/module-operator.html
+import operator
+import struct
+import sys
+import zlib
+# http://www.python.org/doc/2.4.4/lib/module-warnings.html
+import warnings
+
+
+__all__ = ['Image', 'Reader', 'Writer', 'write_chunks', 'from_array']
+
+
+# The PNG signature.
+# http://www.w3.org/TR/PNG/#5PNG-file-signature
+_signature = struct.pack('8B', 137, 80, 78, 71, 13, 10, 26, 10)
+
+_adam7 = ((0, 0, 8, 8),
+ (4, 0, 8, 8),
+ (0, 4, 4, 8),
+ (2, 0, 4, 4),
+ (0, 2, 2, 4),
+ (1, 0, 2, 2),
+ (0, 1, 1, 2))
+
+def group(s, n):
+ # See
+ # http://www.python.org/doc/2.6/library/functions.html#zip
+ return zip(*[iter(s)]*n)
+
+def isarray(x):
+ """Same as ``isinstance(x, array)`` except on Python 2.2, where it
+ always returns ``False``. This helps PyPNG work on Python 2.2.
+ """
+
+ try:
+ return isinstance(x, array)
+ except:
+ return False
+
+try: # see :pyver:old
+ array.tostring
+except:
+ def tostring(row):
+ l = len(row)
+ return struct.pack('%dB' % l, *row)
+else:
+ def tostring(row):
+ """Convert row of bytes to string. Expects `row` to be an
+ ``array``.
+ """
+ return row.tostring()
+
+# Conditionally convert to bytes. Works on Python 2 and Python 3.
+try:
+ bytes('', 'ascii')
+ def strtobytes(x): return bytes(x, 'iso8859-1')
+ def bytestostr(x): return str(x, 'iso8859-1')
+except:
+ strtobytes = str
+ bytestostr = str
+
+def interleave_planes(ipixels, apixels, ipsize, apsize):
+ """
+ Interleave (colour) planes, e.g. RGB + A = RGBA.
+
+ Return an array of pixels consisting of the `ipsize` elements of data
+ from each pixel in `ipixels` followed by the `apsize` elements of data
+ from each pixel in `apixels`. Conventionally `ipixels` and
+ `apixels` are byte arrays so the sizes are bytes, but it actually
+ works with any arrays of the same type. The returned array is the
+ same type as the input arrays which should be the same type as each other.
+ """
+
+ itotal = len(ipixels)
+ atotal = len(apixels)
+ newtotal = itotal + atotal
+ newpsize = ipsize + apsize
+ # Set up the output buffer
+ # See http://www.python.org/doc/2.4.4/lib/module-array.html#l2h-1356
+ out = array(ipixels.typecode)
+ # It's annoying that there is no cheap way to set the array size :-(
+ out.extend(ipixels)
+ out.extend(apixels)
+ # Interleave in the pixel data
+ for i in range(ipsize):
+ out[i:newtotal:newpsize] = ipixels[i:itotal:ipsize]
+ for i in range(apsize):
+ out[i+ipsize:newtotal:newpsize] = apixels[i:atotal:apsize]
+ return out
+
+def check_palette(palette):
+ """Check a palette argument (to the :class:`Writer` class) for validity.
+ Returns the palette as a list if okay; raises an exception otherwise.
+ """
+
+ # None is the default and is allowed.
+ if palette is None:
+ return None
+
+ p = list(palette)
+ if not (0 < len(p) <= 256):
+ raise ValueError("a palette must have between 1 and 256 entries")
+ seen_triple = False
+ for i,t in enumerate(p):
+ if len(t) not in (3,4):
+ raise ValueError(
+ "palette entry %d: entries must be 3- or 4-tuples." % i)
+ if len(t) == 3:
+ seen_triple = True
+ if seen_triple and len(t) == 4:
+ raise ValueError(
+ "palette entry %d: all 4-tuples must precede all 3-tuples" % i)
+ for x in t:
+ if int(x) != x or not(0 <= x <= 255):
+ raise ValueError(
+ "palette entry %d: values must be integer: 0 <= x <= 255" % i)
+ return p
+
+class Error(Exception):
+ prefix = 'Error'
+ def __str__(self):
+ return self.prefix + ': ' + ' '.join(self.args)
+
+class FormatError(Error):
+ """Problem with input file format. In other words, PNG file does
+ not conform to the specification in some way and is invalid.
+ """
+
+ prefix = 'FormatError'
+
+class ChunkError(FormatError):
+ prefix = 'ChunkError'
+
+
+class Writer:
+ """
+ PNG encoder in pure Python.
+ """
+
+ def __init__(self, width=None, height=None,
+ size=None,
+ greyscale=False,
+ alpha=False,
+ bitdepth=8,
+ palette=None,
+ transparent=None,
+ background=None,
+ gamma=None,
+ compression=None,
+ interlace=False,
+ bytes_per_sample=None, # deprecated
+ planes=None,
+ colormap=None,
+ maxval=None,
+ chunk_limit=2**20):
+ """
+ Create a PNG encoder object.
+
+ Arguments:
+
+ width, height
+ Image size in pixels, as two separate arguments.
+ size
+ Image size (w,h) in pixels, as single argument.
+ greyscale
+ Input data is greyscale, not RGB.
+ alpha
+ Input data has alpha channel (RGBA or LA).
+ bitdepth
+ Bit depth: from 1 to 16.
+ palette
+ Create a palette for a colour mapped image (colour type 3).
+ transparent
+ Specify a transparent colour (create a ``tRNS`` chunk).
+ background
+ Specify a default background colour (create a ``bKGD`` chunk).
+ gamma
+ Specify a gamma value (create a ``gAMA`` chunk).
+ compression
+ zlib compression level (1-9).
+ interlace
+ Create an interlaced image.
+ chunk_limit
+ Write multiple ``IDAT`` chunks to save memory.
+
+ The image size (in pixels) can be specified either by using the
+ `width` and `height` arguments, or with the single `size`
+ argument. If `size` is used it should be a pair (*width*,
+ *height*).
+
+ `greyscale` and `alpha` are booleans that specify whether
+ an image is greyscale (or colour), and whether it has an
+ alpha channel (or not).
+
+ `bitdepth` specifies the bit depth of the source pixel values.
+ Each source pixel value must be an integer between 0 and
+ ``2**bitdepth-1``. For example, 8-bit images have values
+ between 0 and 255. PNG only stores images with bit depths of
+ 1,2,4,8, or 16. When `bitdepth` is not one of these values,
+ the next highest valid bit depth is selected, and an ``sBIT``
+ (significant bits) chunk is generated that specifies the original
+ precision of the source image. In this case the supplied pixel
+ values will be rescaled to fit the range of the selected bit depth.
+
+ The details of which bit depth / colour model combinations the
+ PNG file format supports directly, are somewhat arcane
+ (refer to the PNG specification for full details). Briefly:
+ "small" bit depths (1,2,4) are only allowed with greyscale and
+ colour mapped images; colour mapped images cannot have bit depth
+ 16.
+
+ For colour mapped images (in other words, when the `palette`
+ argument is specified) the `bitdepth` argument must match one of
+ the valid PNG bit depths: 1, 2, 4, or 8. (It is valid to have a
+ PNG image with a palette and an ``sBIT`` chunk, but the meaning
+ is slightly different; it would be awkward to press the
+ `bitdepth` argument into service for this.)
+
+ The `palette` option, when specified, causes a colour mapped image
+ to be created: the PNG colour type is set to 3; greyscale
+ must not be set; alpha must not be set; transparent must
+ not be set; the bit depth must be 1,2,4, or 8. When a colour
+ mapped image is created, the pixel values are palette indexes
+ and the `bitdepth` argument specifies the size of these indexes
+ (not the size of the colour values in the palette).
+
+ The palette argument value should be a sequence of 3- or
+ 4-tuples. 3-tuples specify RGB palette entries; 4-tuples
+ specify RGBA palette entries. If both 4-tuples and 3-tuples
+ appear in the sequence then all the 4-tuples must come
+ before all the 3-tuples. A ``PLTE`` chunk is created; if there
+ are 4-tuples then a ``tRNS`` chunk is created as well. The
+ ``PLTE`` chunk will contain all the RGB triples in the same
+ sequence; the ``tRNS`` chunk will contain the alpha channel for
+ all the 4-tuples, in the same sequence. Palette entries
+ are always 8-bit.
+
+ If specified, the `transparent` and `background` parameters must
+ be a tuple with three integer values for red, green, blue, or
+ a simple integer (or singleton tuple) for a greyscale image.
+
+ If specified, the `gamma` parameter must be a positive number
+ (generally, a float). A ``gAMA`` chunk will be created. Note that
+ this will not change the values of the pixels as they appear in
+ the PNG file, they are assumed to have already been converted
+ appropriately for the gamma specified.
+
+ The `compression` argument specifies the compression level
+ to be used by the ``zlib`` module. Higher values are likely
+ to compress better, but will be slower to compress. The
+ default for this argument is ``None``; this does not mean
+ no compression, rather it means that the default from the
+ ``zlib`` module is used (which is generally acceptable).
+
+ If `interlace` is true then an interlaced image is created
+ (using PNG's so far only interace method, *Adam7*). This does not
+ affect how the pixels should be presented to the encoder, rather
+ it changes how they are arranged into the PNG file. On slow
+ connexions interlaced images can be partially decoded by the
+ browser to give a rough view of the image that is successively
+ refined as more image data appears.
+
+ .. note ::
+
+ Enabling the `interlace` option requires the entire image
+ to be processed in working memory.
+
+ `chunk_limit` is used to limit the amount of memory used whilst
+ compressing the image. In order to avoid using large amounts of
+ memory, multiple ``IDAT`` chunks may be created.
+ """
+
+ # At the moment the `planes` argument is ignored;
+ # its purpose is to act as a dummy so that
+ # ``Writer(x, y, **info)`` works, where `info` is a dictionary
+ # returned by Reader.read and friends.
+ # Ditto for `colormap`.
+
+ # A couple of helper functions come first. Best skipped if you
+ # are reading through.
+
+ def isinteger(x):
+ try:
+ return int(x) == x
+ except:
+ return False
+
+ def check_color(c, which):
+ """Checks that a colour argument for transparent or
+ background options is the right form. Also "corrects" bare
+ integers to 1-tuples.
+ """
+
+ if c is None:
+ return c
+ if greyscale:
+ try:
+ l = len(c)
+ except TypeError:
+ c = (c,)
+ if len(c) != 1:
+ raise ValueError("%s for greyscale must be 1-tuple" %
+ which)
+ if not isinteger(c[0]):
+ raise ValueError(
+ "%s colour for greyscale must be integer" %
+ which)
+ else:
+ if not (len(c) == 3 and
+ isinteger(c[0]) and
+ isinteger(c[1]) and
+ isinteger(c[2])):
+ raise ValueError(
+ "%s colour must be a triple of integers" %
+ which)
+ return c
+
+ if size:
+ if len(size) != 2:
+ raise ValueError(
+ "size argument should be a pair (width, height)")
+ if width is not None and width != size[0]:
+ raise ValueError(
+ "size[0] (%r) and width (%r) should match when both are used."
+ % (size[0], width))
+ if height is not None and height != size[1]:
+ raise ValueError(
+ "size[1] (%r) and height (%r) should match when both are used."
+ % (size[1], height))
+ width,height = size
+ del size
+
+ if width <= 0 or height <= 0:
+ raise ValueError("width and height must be greater than zero")
+ if not isinteger(width) or not isinteger(height):
+ raise ValueError("width and height must be integers")
+ # http://www.w3.org/TR/PNG/#7Integers-and-byte-order
+ if width > 2**32-1 or height > 2**32-1:
+ raise ValueError("width and height cannot exceed 2**32-1")
+
+ if alpha and transparent is not None:
+ raise ValueError(
+ "transparent colour not allowed with alpha channel")
+
+ if bytes_per_sample is not None:
+ warnings.warn('please use bitdepth instead of bytes_per_sample',
+ DeprecationWarning)
+ if bytes_per_sample not in (0.125, 0.25, 0.5, 1, 2):
+ raise ValueError(
+ "bytes per sample must be .125, .25, .5, 1, or 2")
+ bitdepth = int(8*bytes_per_sample)
+ del bytes_per_sample
+ if not isinteger(bitdepth) or bitdepth < 1 or 16 < bitdepth:
+ raise ValueError("bitdepth (%r) must be a postive integer <= 16" %
+ bitdepth)
+
+ self.rescale = None
+ if palette:
+ if bitdepth not in (1,2,4,8):
+ raise ValueError("with palette, bitdepth must be 1, 2, 4, or 8")
+ if transparent is not None:
+ raise ValueError("transparent and palette not compatible")
+ if alpha:
+ raise ValueError("alpha and palette not compatible")
+ if greyscale:
+ raise ValueError("greyscale and palette not compatible")
+ else:
+ # No palette, check for sBIT chunk generation.
+ if alpha or not greyscale:
+ if bitdepth not in (8,16):
+ targetbitdepth = (8,16)[bitdepth > 8]
+ self.rescale = (bitdepth, targetbitdepth)
+ bitdepth = targetbitdepth
+ del targetbitdepth
+ else:
+ assert greyscale
+ assert not alpha
+ if bitdepth not in (1,2,4,8,16):
+ if bitdepth > 8:
+ targetbitdepth = 16
+ elif bitdepth == 3:
+ targetbitdepth = 4
+ else:
+ assert bitdepth in (5,6,7)
+ targetbitdepth = 8
+ self.rescale = (bitdepth, targetbitdepth)
+ bitdepth = targetbitdepth
+ del targetbitdepth
+
+ if bitdepth < 8 and (alpha or not greyscale and not palette):
+ raise ValueError(
+ "bitdepth < 8 only permitted with greyscale or palette")
+ if bitdepth > 8 and palette:
+ raise ValueError(
+ "bit depth must be 8 or less for images with palette")
+
+ transparent = check_color(transparent, 'transparent')
+ background = check_color(background, 'background')
+
+ # It's important that the true boolean values (greyscale, alpha,
+ # colormap, interlace) are converted to bool because Iverson's
+ # convention is relied upon later on.
+ self.width = width
+ self.height = height
+ self.transparent = transparent
+ self.background = background
+ self.gamma = gamma
+ self.greyscale = bool(greyscale)
+ self.alpha = bool(alpha)
+ self.colormap = bool(palette)
+ self.bitdepth = int(bitdepth)
+ self.compression = compression
+ self.chunk_limit = chunk_limit
+ self.interlace = bool(interlace)
+ self.palette = check_palette(palette)
+
+ self.color_type = 4*self.alpha + 2*(not greyscale) + 1*self.colormap
+ assert self.color_type in (0,2,3,4,6)
+
+ self.color_planes = (3,1)[self.greyscale or self.colormap]
+ self.planes = self.color_planes + self.alpha
+ # :todo: fix for bitdepth < 8
+ self.psize = (self.bitdepth/8) * self.planes
+
+ def make_palette(self):
+ """Create the byte sequences for a ``PLTE`` and if necessary a
+ ``tRNS`` chunk. Returned as a pair (*p*, *t*). *t* will be
+ ``None`` if no ``tRNS`` chunk is necessary.
+ """
+
+ p = array('B')
+ t = array('B')
+
+ for x in self.palette:
+ p.extend(x[0:3])
+ if len(x) > 3:
+ t.append(x[3])
+ p = tostring(p)
+ t = tostring(t)
+ if t:
+ return p,t
+ return p,None
+
+ def write(self, outfile, rows):
+ """Write a PNG image to the output file. `rows` should be
+ an iterable that yields each row in boxed row flat pixel format.
+ The rows should be the rows of the original image, so there
+ should be ``self.height`` rows of ``self.width * self.planes`` values.
+ If `interlace` is specified (when creating the instance), then
+ an interlaced PNG file will be written. Supply the rows in the
+ normal image order; the interlacing is carried out internally.
+
+ .. note ::
+
+ Interlacing will require the entire image to be in working memory.
+ """
+
+ if self.interlace:
+ fmt = 'BH'[self.bitdepth > 8]
+ a = array(fmt, itertools.chain(*rows))
+ return self.write_array(outfile, a)
+ else:
+ nrows = self.write_passes(outfile, rows)
+ if nrows != self.height:
+ raise ValueError(
+ "rows supplied (%d) does not match height (%d)" %
+ (nrows, self.height))
+
+ def write_passes(self, outfile, rows, packed=False):
+ """
+ Write a PNG image to the output file.
+
+ Most users are expected to find the :meth:`write` or
+ :meth:`write_array` method more convenient.
+
+ The rows should be given to this method in the order that
+ they appear in the output file. For straightlaced images,
+ this is the usual top to bottom ordering, but for interlaced
+ images the rows should have already been interlaced before
+ passing them to this function.
+
+ `rows` should be an iterable that yields each row. When
+ `packed` is ``False`` the rows should be in boxed row flat pixel
+ format; when `packed` is ``True`` each row should be a packed
+ sequence of bytes.
+
+ """
+
+ # http://www.w3.org/TR/PNG/#5PNG-file-signature
+ outfile.write(_signature)
+
+ # http://www.w3.org/TR/PNG/#11IHDR
+ write_chunk(outfile, 'IHDR',
+ struct.pack("!2I5B", self.width, self.height,
+ self.bitdepth, self.color_type,
+ 0, 0, self.interlace))
+
+ # See :chunk:order
+ # http://www.w3.org/TR/PNG/#11gAMA
+ if self.gamma is not None:
+ write_chunk(outfile, 'gAMA',
+ struct.pack("!L", int(round(self.gamma*1e5))))
+
+ # See :chunk:order
+ # http://www.w3.org/TR/PNG/#11sBIT
+ if self.rescale:
+ write_chunk(outfile, 'sBIT',
+ struct.pack('%dB' % self.planes,
+ *[self.rescale[0]]*self.planes))
+
+ # :chunk:order: Without a palette (PLTE chunk), ordering is
+ # relatively relaxed. With one, gAMA chunk must precede PLTE
+ # chunk which must precede tRNS and bKGD.
+ # See http://www.w3.org/TR/PNG/#5ChunkOrdering
+ if self.palette:
+ p,t = self.make_palette()
+ write_chunk(outfile, 'PLTE', p)
+ if t:
+ # tRNS chunk is optional. Only needed if palette entries
+ # have alpha.
+ write_chunk(outfile, 'tRNS', t)
+
+ # http://www.w3.org/TR/PNG/#11tRNS
+ if self.transparent is not None:
+ if self.greyscale:
+ write_chunk(outfile, 'tRNS',
+ struct.pack("!1H", *self.transparent))
+ else:
+ write_chunk(outfile, 'tRNS',
+ struct.pack("!3H", *self.transparent))
+
+ # http://www.w3.org/TR/PNG/#11bKGD
+ if self.background is not None:
+ if self.greyscale:
+ write_chunk(outfile, 'bKGD',
+ struct.pack("!1H", *self.background))
+ else:
+ write_chunk(outfile, 'bKGD',
+ struct.pack("!3H", *self.background))
+
+ # http://www.w3.org/TR/PNG/#11IDAT
+ if self.compression is not None:
+ compressor = zlib.compressobj(self.compression)
+ else:
+ compressor = zlib.compressobj()
+
+ # Choose an extend function based on the bitdepth. The extend
+ # function packs/decomposes the pixel values into bytes and
+ # stuffs them onto the data array.
+ data = array('B')
+ if self.bitdepth == 8 or packed:
+ extend = data.extend
+ elif self.bitdepth == 16:
+ # Decompose into bytes
+ def extend(sl):
+ fmt = '!%dH' % len(sl)
+ data.extend(array('B', struct.pack(fmt, *sl)))
+ else:
+ # Pack into bytes
+ assert self.bitdepth < 8
+ # samples per byte
+ spb = int(8/self.bitdepth)
+ def extend(sl):
+ a = array('B', sl)
+ # Adding padding bytes so we can group into a whole
+ # number of spb-tuples.
+ l = float(len(a))
+ extra = math.ceil(l / float(spb))*spb - l
+ a.extend([0]*int(extra))
+ # Pack into bytes
+ l = group(a, spb)
+ l = map(lambda e: reduce(lambda x,y:
+ (x << self.bitdepth) + y, e), l)
+ data.extend(l)
+ if self.rescale:
+ oldextend = extend
+ factor = \
+ float(2**self.rescale[1]-1) / float(2**self.rescale[0]-1)
+ def extend(sl):
+ oldextend(map(lambda x: int(round(factor*x)), sl))
+
+ # Build the first row, testing mostly to see if we need to
+ # changed the extend function to cope with NumPy integer types
+ # (they cause our ordinary definition of extend to fail, so we
+ # wrap it). See
+ # http://code.google.com/p/pypng/issues/detail?id=44
+ enumrows = enumerate(rows)
+ del rows
+
+ # First row's filter type.
+ data.append(0)
+ # :todo: Certain exceptions in the call to ``.next()`` or the
+ # following try would indicate no row data supplied.
+ # Should catch.
+ i,row = enumrows.next()
+ try:
+ # If this fails...
+ extend(row)
+ except:
+ # ... try a version that converts the values to int first.
+ # Not only does this work for the (slightly broken) NumPy
+ # types, there are probably lots of other, unknown, "nearly"
+ # int types it works for.
+ def wrapmapint(f):
+ return lambda sl: f(map(int, sl))
+ extend = wrapmapint(extend)
+ del wrapmapint
+ extend(row)
+
+ for i,row in enumrows:
+ # Add "None" filter type. Currently, it's essential that
+ # this filter type be used for every scanline as we do not
+ # mark the first row of a reduced pass image; that means we
+ # could accidentally compute the wrong filtered scanline if
+ # we used "up", "average", or "paeth" on such a line.
+ data.append(0)
+ extend(row)
+ if len(data) > self.chunk_limit:
+ compressed = compressor.compress(tostring(data))
+ if len(compressed):
+ # print >> sys.stderr, len(data), len(compressed)
+ write_chunk(outfile, 'IDAT', compressed)
+ # Because of our very witty definition of ``extend``,
+ # above, we must re-use the same ``data`` object. Hence
+ # we use ``del`` to empty this one, rather than create a
+ # fresh one (which would be my natural FP instinct).
+ del data[:]
+ if len(data):
+ compressed = compressor.compress(tostring(data))
+ else:
+ compressed = ''
+ flushed = compressor.flush()
+ if len(compressed) or len(flushed):
+ # print >> sys.stderr, len(data), len(compressed), len(flushed)
+ write_chunk(outfile, 'IDAT', compressed + flushed)
+ # http://www.w3.org/TR/PNG/#11IEND
+ write_chunk(outfile, 'IEND')
+ return i+1
+
+ def write_array(self, outfile, pixels):
+ """
+ Write an array in flat row flat pixel format as a PNG file on
+ the output file. See also :meth:`write` method.
+ """
+
+ if self.interlace:
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.array_scanlines(pixels))
+
+ def write_packed(self, outfile, rows):
+ """
+ Write PNG file to `outfile`. The pixel data comes from `rows`
+ which should be in boxed row packed format. Each row should be
+ a sequence of packed bytes.
+
+ Technically, this method does work for interlaced images but it
+ is best avoided. For interlaced images, the rows should be
+ presented in the order that they appear in the file.
+
+ This method should not be used when the source image bit depth
+ is not one naturally supported by PNG; the bit depth should be
+ 1, 2, 4, 8, or 16.
+ """
+
+ if self.rescale:
+ raise Error("write_packed method not suitable for bit depth %d" %
+ self.rescale[0])
+ return self.write_passes(outfile, rows, packed=True)
+
+ def convert_pnm(self, infile, outfile):
+ """
+ Convert a PNM file containing raw pixel data into a PNG file
+ with the parameters set in the writer object. Works for
+ (binary) PGM, PPM, and PAM formats.
+ """
+
+ if self.interlace:
+ pixels = array('B')
+ pixels.fromfile(infile,
+ (self.bitdepth/8) * self.color_planes *
+ self.width * self.height)
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.file_scanlines(infile))
+
+ def convert_ppm_and_pgm(self, ppmfile, pgmfile, outfile):
+ """
+ Convert a PPM and PGM file containing raw pixel data into a
+ PNG outfile with the parameters set in the writer object.
+ """
+ pixels = array('B')
+ pixels.fromfile(ppmfile,
+ (self.bitdepth/8) * self.color_planes *
+ self.width * self.height)
+ apixels = array('B')
+ apixels.fromfile(pgmfile,
+ (self.bitdepth/8) *
+ self.width * self.height)
+ pixels = interleave_planes(pixels, apixels,
+ (self.bitdepth/8) * self.color_planes,
+ (self.bitdepth/8))
+ if self.interlace:
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.array_scanlines(pixels))
+
+ def file_scanlines(self, infile):
+ """
+ Generates boxed rows in flat pixel format, from the input file
+ `infile`. It assumes that the input file is in a "Netpbm-like"
+ binary format, and is positioned at the beginning of the first
+ pixel. The number of pixels to read is taken from the image
+ dimensions (`width`, `height`, `planes`) and the number of bytes
+ per value is implied by the image `bitdepth`.
+ """
+
+ # Values per row
+ vpr = self.width * self.planes
+ row_bytes = vpr
+ if self.bitdepth > 8:
+ assert self.bitdepth == 16
+ row_bytes *= 2
+ fmt = '>%dH' % vpr
+ def line():
+ return array('H', struct.unpack(fmt, infile.read(row_bytes)))
+ else:
+ def line():
+ scanline = array('B', infile.read(row_bytes))
+ return scanline
+ for y in range(self.height):
+ yield line()
+
+ def array_scanlines(self, pixels):
+ """
+ Generates boxed rows (flat pixels) from flat rows (flat pixels)
+ in an array.
+ """
+
+ # Values per row
+ vpr = self.width * self.planes
+ stop = 0
+ for y in range(self.height):
+ start = stop
+ stop = start + vpr
+ yield pixels[start:stop]
+
+ def array_scanlines_interlace(self, pixels):
+ """
+ Generator for interlaced scanlines from an array. `pixels` is
+ the full source image in flat row flat pixel format. The
+ generator yields each scanline of the reduced passes in turn, in
+ boxed row flat pixel format.
+ """
+
+ # http://www.w3.org/TR/PNG/#8InterlaceMethods
+ # Array type.
+ fmt = 'BH'[self.bitdepth > 8]
+ # Value per row
+ vpr = self.width * self.planes
+ for xstart, ystart, xstep, ystep in _adam7:
+ if xstart >= self.width:
+ continue
+ # Pixels per row (of reduced image)
+ ppr = int(math.ceil((self.width-xstart)/float(xstep)))
+ # number of values in reduced image row.
+ row_len = ppr*self.planes
+ for y in range(ystart, self.height, ystep):
+ if xstep == 1:
+ offset = y * vpr
+ yield pixels[offset:offset+vpr]
+ else:
+ row = array(fmt)
+ # There's no easier way to set the length of an array
+ row.extend(pixels[0:row_len])
+ offset = y * vpr + xstart * self.planes
+ end_offset = (y+1) * vpr
+ skip = self.planes * xstep
+ for i in range(self.planes):
+ row[i::self.planes] = \
+ pixels[offset+i:end_offset:skip]
+ yield row
+
+def write_chunk(outfile, tag, data=strtobytes('')):
+ """
+ Write a PNG chunk to the output file, including length and
+ checksum.
+ """
+
+ # http://www.w3.org/TR/PNG/#5Chunk-layout
+ outfile.write(struct.pack("!I", len(data)))
+ tag = strtobytes(tag)
+ outfile.write(tag)
+ outfile.write(data)
+ checksum = zlib.crc32(tag)
+ checksum = zlib.crc32(data, checksum)
+ checksum &= 2**32-1
+ outfile.write(struct.pack("!I", checksum))
+
+def write_chunks(out, chunks):
+ """Create a PNG file by writing out the chunks."""
+
+ out.write(_signature)
+ for chunk in chunks:
+ write_chunk(out, *chunk)
+
+def filter_scanline(type, line, fo, prev=None):
+ """Apply a scanline filter to a scanline. `type` specifies the
+ filter type (0 to 4); `line` specifies the current (unfiltered)
+ scanline as a sequence of bytes; `prev` specifies the previous
+ (unfiltered) scanline as a sequence of bytes. `fo` specifies the
+ filter offset; normally this is size of a pixel in bytes (the number
+ of bytes per sample times the number of channels), but when this is
+ < 1 (for bit depths < 8) then the filter offset is 1.
+ """
+
+ assert 0 <= type < 5
+
+ # The output array. Which, pathetically, we extend one-byte at a
+ # time (fortunately this is linear).
+ out = array('B', [type])
+
+ def sub():
+ ai = -fo
+ for x in line:
+ if ai >= 0:
+ x = (x - line[ai]) & 0xff
+ out.append(x)
+ ai += 1
+ def up():
+ for i,x in enumerate(line):
+ x = (x - prev[i]) & 0xff
+ out.append(x)
+ def average():
+ ai = -fo
+ for i,x in enumerate(line):
+ if ai >= 0:
+ x = (x - ((line[ai] + prev[i]) >> 1)) & 0xff
+ else:
+ x = (x - (prev[i] >> 1)) & 0xff
+ out.append(x)
+ ai += 1
+ def paeth():
+ # http://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
+ ai = -fo # also used for ci
+ for i,x in enumerate(line):
+ a = 0
+ b = prev[i]
+ c = 0
+
+ if ai >= 0:
+ a = line[ai]
+ c = prev[ai]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc: Pr = a
+ elif pb <= pc: Pr = b
+ else: Pr = c
+
+ x = (x - Pr) & 0xff
+ out.append(x)
+ ai += 1
+
+ if not prev:
+ # We're on the first line. Some of the filters can be reduced
+ # to simpler cases which makes handling the line "off the top"
+ # of the image simpler. "up" becomes "none"; "paeth" becomes
+ # "left" (non-trivial, but true). "average" needs to be handled
+ # specially.
+ if type == 2: # "up"
+ return line # type = 0
+ elif type == 3:
+ prev = [0]*len(line)
+ elif type == 4: # "paeth"
+ type = 1
+ if type == 0:
+ out.extend(line)
+ elif type == 1:
+ sub()
+ elif type == 2:
+ up()
+ elif type == 3:
+ average()
+ else: # type == 4
+ paeth()
+ return out
+
+
+def from_array(a, mode=None, info={}):
+ """Create a PNG :class:`Image` object from a 2- or 3-dimensional array.
+ One application of this function is easy PIL-style saving:
+ ``png.from_array(pixels, 'L').save('foo.png')``.
+
+ .. note :
+
+ The use of the term *3-dimensional* is for marketing purposes
+ only. It doesn't actually work. Please bear with us. Meanwhile
+ enjoy the complimentary snacks (on request) and please use a
+ 2-dimensional array.
+
+ Unless they are specified using the *info* parameter, the PNG's
+ height and width are taken from the array size. For a 3 dimensional
+ array the first axis is the height; the second axis is the width;
+ and the third axis is the channel number. Thus an RGB image that is
+ 16 pixels high and 8 wide will use an array that is 16x8x3. For 2
+ dimensional arrays the first axis is the height, but the second axis
+ is ``width*channels``, so an RGB image that is 16 pixels high and 8
+ wide will use a 2-dimensional array that is 16x24 (each row will be
+ 8*3==24 sample values).
+
+ *mode* is a string that specifies the image colour format in a
+ PIL-style mode. It can be:
+
+ ``'L'``
+ greyscale (1 channel)
+ ``'LA'``
+ greyscale with alpha (2 channel)
+ ``'RGB'``
+ colour image (3 channel)
+ ``'RGBA'``
+ colour image with alpha (4 channel)
+
+ The mode string can also specify the bit depth (overriding how this
+ function normally derives the bit depth, see below). Appending
+ ``';16'`` to the mode will cause the PNG to be 16 bits per channel;
+ any decimal from 1 to 16 can be used to specify the bit depth.
+
+ When a 2-dimensional array is used *mode* determines how many
+ channels the image has, and so allows the width to be derived from
+ the second array dimension.
+
+ The array is expected to be a ``numpy`` array, but it can be any
+ suitable Python sequence. For example, a list of lists can be used:
+ ``png.from_array([[0, 255, 0], [255, 0, 255]], 'L')``. The exact
+ rules are: ``len(a)`` gives the first dimension, height;
+ ``len(a[0])`` gives the second dimension; ``len(a[0][0])`` gives the
+ third dimension, unless an exception is raised in which case a
+ 2-dimensional array is assumed. It's slightly more complicated than
+ that because an iterator of rows can be used, and it all still
+ works. Using an iterator allows data to be streamed efficiently.
+
+ The bit depth of the PNG is normally taken from the array element's
+ datatype (but if *mode* specifies a bitdepth then that is used
+ instead). The array element's datatype is determined in a way which
+ is supposed to work both for ``numpy`` arrays and for Python
+ ``array.array`` objects. A 1 byte datatype will give a bit depth of
+ 8, a 2 byte datatype will give a bit depth of 16. If the datatype
+ does not have an implicit size, for example it is a plain Python
+ list of lists, as above, then a default of 8 is used.
+
+ The *info* parameter is a dictionary that can be used to specify
+ metadata (in the same style as the arguments to the
+ :class:``png.Writer`` class). For this function the keys that are
+ useful are:
+
+ height
+ overrides the height derived from the array dimensions and allows
+ *a* to be an iterable.
+ width
+ overrides the width derived from the array dimensions.
+ bitdepth
+ overrides the bit depth derived from the element datatype (but
+ must match *mode* if that also specifies a bit depth).
+
+ Generally anything specified in the
+ *info* dictionary will override any implicit choices that this
+ function would otherwise make, but must match any explicit ones.
+ For example, if the *info* dictionary has a ``greyscale`` key then
+ this must be true when mode is ``'L'`` or ``'LA'`` and false when
+ mode is ``'RGB'`` or ``'RGBA'``.
+ """
+
+ # We abuse the *info* parameter by modifying it. Take a copy here.
+ # (Also typechecks *info* to some extent).
+ info = dict(info)
+
+ # Syntax check mode string.
+ bitdepth = None
+ try:
+ mode = mode.split(';')
+ if len(mode) not in (1,2):
+ raise Error()
+ if mode[0] not in ('L', 'LA', 'RGB', 'RGBA'):
+ raise Error()
+ if len(mode) == 2:
+ try:
+ bitdepth = int(mode[1])
+ except:
+ raise Error()
+ except Error:
+ raise Error("mode string should be 'RGB' or 'L;16' or similar.")
+ mode = mode[0]
+
+ # Get bitdepth from *mode* if possible.
+ if bitdepth:
+ if info.get('bitdepth') and bitdepth != info['bitdepth']:
+ raise Error("mode bitdepth (%d) should match info bitdepth (%d)." %
+ (bitdepth, info['bitdepth']))
+ info['bitdepth'] = bitdepth
+
+ # Fill in and/or check entries in *info*.
+ # Dimensions.
+ if 'size' in info:
+ # Check width, height, size all match where used.
+ for dimension,axis in [('width', 0), ('height', 1)]:
+ if dimension in info:
+ if info[dimension] != info['size'][axis]:
+ raise Error(
+ "info[%r] shhould match info['size'][%r]." %
+ (dimension, axis))
+ info['width'],info['height'] = info['size']
+ if 'height' not in info:
+ try:
+ l = len(a)
+ except:
+ raise Error(
+ "len(a) does not work, supply info['height'] instead.")
+ info['height'] = l
+ # Colour format.
+ if 'greyscale' in info:
+ if bool(info['greyscale']) != ('L' in mode):
+ raise Error("info['greyscale'] should match mode.")
+ info['greyscale'] = 'L' in mode
+ if 'alpha' in info:
+ if bool(info['alpha']) != ('A' in mode):
+ raise Error("info['alpha'] should match mode.")
+ info['alpha'] = 'A' in mode
+
+ planes = len(mode)
+ if 'planes' in info:
+ if info['planes'] != planes:
+ raise Error("info['planes'] should match mode.")
+
+ # In order to work out whether we the array is 2D or 3D we need its
+ # first row, which requires that we take a copy of its iterator.
+ # We may also need the first row to derive width and bitdepth.
+ a,t = itertools.tee(a)
+ row = t.next()
+ del t
+ try:
+ row[0][0]
+ threed = True
+ testelement = row[0]
+ except:
+ threed = False
+ testelement = row
+ if 'width' not in info:
+ if threed:
+ width = len(row)
+ else:
+ width = len(row) // planes
+ info['width'] = width
+
+ # Not implemented yet
+ assert not threed
+
+ if 'bitdepth' not in info:
+ try:
+ dtype = testelement.dtype
+ # goto the "else:" clause. Sorry.
+ except:
+ try:
+ # Try a Python array.array.
+ bitdepth = 8 * testelement.itemsize
+ except:
+ # We can't determine it from the array element's
+ # datatype, use a default of 8.
+ bitdepth = 8
+ else:
+ # If we got here without exception, we now assume that
+ # the array is a numpy array.
+ if dtype.kind == 'b':
+ bitdepth = 1
+ else:
+ bitdepth = 8 * dtype.itemsize
+ info['bitdepth'] = bitdepth
+
+ for thing in 'width height bitdepth greyscale alpha'.split():
+ assert thing in info
+ return Image(a, info)
+
+# So that refugee's from PIL feel more at home. Not documented.
+fromarray = from_array
+
+class Image:
+ """A PNG image.
+ You can create an :class:`Image` object from an array of pixels by calling
+ :meth:`png.from_array`. It can be saved to disk with the
+ :meth:`save` method."""
+ def __init__(self, rows, info):
+ """
+ .. note ::
+
+ The constructor is not public. Please do not call it.
+ """
+
+ self.rows = rows
+ self.info = info
+
+ def save(self, file):
+ """Save the image to *file*. If *file* looks like an open file
+ descriptor then it is used, otherwise it is treated as a
+ filename and a fresh file is opened.
+
+ In general, you can only call this method once; after it has
+ been called the first time and the PNG image has been saved, the
+ source data will have been streamed, and cannot be streamed
+ again.
+ """
+
+ w = Writer(**self.info)
+
+ try:
+ file.write
+ def close(): pass
+ except:
+ file = open(file, 'wb')
+ def close(): file.close()
+
+ try:
+ w.write(file, self.rows)
+ finally:
+ close()
+
+class _readable:
+ """
+ A simple file-like interface for strings and arrays.
+ """
+
+ def __init__(self, buf):
+ self.buf = buf
+ self.offset = 0
+
+ def read(self, n):
+ r = self.buf[self.offset:self.offset+n]
+ if isarray(r):
+ r = r.tostring()
+ self.offset += n
+ return r
+
+
+class Reader:
+ """
+ PNG decoder in pure Python.
+ """
+
+ def __init__(self, _guess=None, **kw):
+ """
+ Create a PNG decoder object.
+
+ The constructor expects exactly one keyword argument. If you
+ supply a positional argument instead, it will guess the input
+ type. You can choose among the following keyword arguments:
+
+ filename
+ Name of input file (a PNG file).
+ file
+ A file-like object (object with a read() method).
+ bytes
+ ``array`` or ``string`` with PNG data.
+
+ """
+ if ((_guess is not None and len(kw) != 0) or
+ (_guess is None and len(kw) != 1)):
+ raise TypeError("Reader() takes exactly 1 argument")
+
+ # Will be the first 8 bytes, later on. See validate_signature.
+ self.signature = None
+ self.transparent = None
+ # A pair of (len,type) if a chunk has been read but its data and
+ # checksum have not (in other words the file position is just
+ # past the 4 bytes that specify the chunk type). See preamble
+ # method for how this is used.
+ self.atchunk = None
+
+ if _guess is not None:
+ if isarray(_guess):
+ kw["bytes"] = _guess
+ elif isinstance(_guess, str):
+ kw["filename"] = _guess
+ elif isinstance(_guess, file):
+ kw["file"] = _guess
+
+ if "filename" in kw:
+ self.file = open(kw["filename"], "rb")
+ elif "file" in kw:
+ self.file = kw["file"]
+ elif "bytes" in kw:
+ self.file = _readable(kw["bytes"])
+ else:
+ raise TypeError("expecting filename, file or bytes array")
+
+ def chunk(self, seek=None):
+ """
+ Read the next PNG chunk from the input file; returns a
+ (*type*,*data*) tuple. *type* is the chunk's type as a string
+ (all PNG chunk types are 4 characters long). *data* is the
+ chunk's data content, as a string.
+
+ If the optional `seek` argument is
+ specified then it will keep reading chunks until it either runs
+ out of file or finds the type specified by the argument. Note
+ that in general the order of chunks in PNGs is unspecified, so
+ using `seek` can cause you to miss chunks.
+ """
+
+ self.validate_signature()
+
+ while True:
+ # http://www.w3.org/TR/PNG/#5Chunk-layout
+ if not self.atchunk:
+ self.atchunk = self.chunklentype()
+ length,type = self.atchunk
+ self.atchunk = None
+ data = self.file.read(length)
+ if len(data) != length:
+ raise ChunkError('Chunk %s too short for required %i octets.'
+ % (type, length))
+ checksum = self.file.read(4)
+ if len(checksum) != 4:
+ raise ValueError('Chunk %s too short for checksum.', tag)
+ if seek and type != seek:
+ continue
+ verify = zlib.crc32(strtobytes(type))
+ verify = zlib.crc32(data, verify)
+ # Whether the output from zlib.crc32 is signed or not varies
+ # according to hideous implementation details, see
+ # http://bugs.python.org/issue1202 .
+ # We coerce it to be positive here (in a way which works on
+ # Python 2.3 and older).
+ verify &= 2**32 - 1
+ verify = struct.pack('!I', verify)
+ if checksum != verify:
+ # print repr(checksum)
+ (a, ) = struct.unpack('!I', checksum)
+ (b, ) = struct.unpack('!I', verify)
+ raise ChunkError(
+ "Checksum error in %s chunk: 0x%08X != 0x%08X." %
+ (type, a, b))
+ return type, data
+
+ def chunks(self):
+ """Return an iterator that will yield each chunk as a
+ (*chunktype*, *content*) pair.
+ """
+
+ while True:
+ t,v = self.chunk()
+ yield t,v
+ if t == 'IEND':
+ break
+
+ def undo_filter(self, filter_type, scanline, previous):
+ """Undo the filter for a scanline. `scanline` is a sequence of
+ bytes that does not include the initial filter type byte.
+ `previous` is decoded previous scanline (for straightlaced
+ images this is the previous pixel row, but for interlaced
+ images, it is the previous scanline in the reduced image, which
+ in general is not the previous pixel row in the final image).
+ When there is no previous scanline (the first row of a
+ straightlaced image, or the first row in one of the passes in an
+ interlaced image), then this argument should be ``None``.
+
+ The scanline will have the effects of filtering removed, and the
+ result will be returned as a fresh sequence of bytes.
+ """
+
+ # :todo: Would it be better to update scanline in place?
+
+ # Create the result byte array. It seems that the best way to
+ # create the array to be the right size is to copy from an
+ # existing sequence. *sigh*
+ # If we fill the result with scanline, then this allows a
+ # micro-optimisation in the "null" and "sub" cases.
+ result = array('B', scanline)
+
+ if filter_type == 0:
+ # And here, we _rely_ on filling the result with scanline,
+ # above.
+ return result
+
+ if filter_type not in (1,2,3,4):
+ raise FormatError('Invalid PNG Filter Type.'
+ ' See http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters .')
+
+ # Filter unit. The stride from one pixel to the corresponding
+ # byte from the previous previous. Normally this is the pixel
+ # size in bytes, but when this is smaller than 1, the previous
+ # byte is used instead.
+ fu = max(1, self.psize)
+
+ # For the first line of a pass, synthesize a dummy previous
+ # line. An alternative approach would be to observe that on the
+ # first line 'up' is the same as 'null', 'paeth' is the same
+ # as 'sub', with only 'average' requiring any special case.
+ if not previous:
+ previous = array('B', [0]*len(scanline))
+
+ def sub():
+ """Undo sub filter."""
+
+ ai = 0
+ # Loops starts at index fu. Observe that the initial part
+ # of the result is already filled in correctly with
+ # scanline.
+ for i in range(fu, len(result)):
+ x = scanline[i]
+ a = result[ai]
+ result[i] = (x + a) & 0xff
+ ai += 1
+
+ def up():
+ """Undo up filter."""
+
+ for i in range(len(result)):
+ x = scanline[i]
+ b = previous[i]
+ result[i] = (x + b) & 0xff
+
+ def average():
+ """Undo average filter."""
+
+ ai = -fu
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = 0
+ else:
+ a = result[ai]
+ b = previous[i]
+ result[i] = (x + ((a + b) >> 1)) & 0xff
+ ai += 1
+
+ def paeth():
+ """Undo Paeth filter."""
+
+ # Also used for ci.
+ ai = -fu
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = c = 0
+ else:
+ a = result[ai]
+ c = previous[ai]
+ b = previous[i]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc:
+ pr = a
+ elif pb <= pc:
+ pr = b
+ else:
+ pr = c
+ result[i] = (x + pr) & 0xff
+ ai += 1
+
+ # Call appropriate filter algorithm. Note that 0 has already
+ # been dealt with.
+ (None, sub, up, average, paeth)[filter_type]()
+ return result
+
+ def deinterlace(self, raw):
+ """
+ Read raw pixel data, undo filters, deinterlace, and flatten.
+ Return in flat row flat pixel format.
+ """
+
+ # print >> sys.stderr, ("Reading interlaced, w=%s, r=%s, planes=%s," +
+ # " bpp=%s") % (self.width, self.height, self.planes, self.bps)
+ # Values per row (of the target image)
+ vpr = self.width * self.planes
+
+ # Make a result array, and make it big enough. Interleaving
+ # writes to the output array randomly (well, not quite), so the
+ # entire output array must be in memory.
+ fmt = 'BH'[self.bitdepth > 8]
+ a = array(fmt, [0]*vpr*self.height)
+ source_offset = 0
+
+ for xstart, ystart, xstep, ystep in _adam7:
+ # print >> sys.stderr, "Adam7: start=%s,%s step=%s,%s" % (
+ # xstart, ystart, xstep, ystep)
+ if xstart >= self.width:
+ continue
+ # The previous (reconstructed) scanline. None at the
+ # beginning of a pass to indicate that there is no previous
+ # line.
+ recon = None
+ # Pixels per row (reduced pass image)
+ ppr = int(math.ceil((self.width-xstart)/float(xstep)))
+ # Row size in bytes for this pass.
+ row_size = int(math.ceil(self.psize * ppr))
+ for y in range(ystart, self.height, ystep):
+ filter_type = raw[source_offset]
+ source_offset += 1
+ scanline = raw[source_offset:source_offset+row_size]
+ source_offset += row_size
+ recon = self.undo_filter(filter_type, scanline, recon)
+ # Convert so that there is one element per pixel value
+ flat = self.serialtoflat(recon, ppr)
+ if xstep == 1:
+ assert xstart == 0
+ offset = y * vpr
+ a[offset:offset+vpr] = flat
+ else:
+ offset = y * vpr + xstart * self.planes
+ end_offset = (y+1) * vpr
+ skip = self.planes * xstep
+ for i in range(self.planes):
+ a[offset+i:end_offset:skip] = \
+ flat[i::self.planes]
+ return a
+
+ def iterboxed(self, rows):
+ """Iterator that yields each scanline in boxed row flat pixel
+ format. `rows` should be an iterator that yields the bytes of
+ each row in turn.
+ """
+
+ def asvalues(raw):
+ """Convert a row of raw bytes into a flat row. Result may
+ or may not share with argument"""
+
+ if self.bitdepth == 8:
+ return raw
+ if self.bitdepth == 16:
+ raw = tostring(raw)
+ return array('H', struct.unpack('!%dH' % (len(raw)//2), raw))
+ assert self.bitdepth < 8
+ width = self.width
+ # Samples per byte
+ spb = 8//self.bitdepth
+ out = array('B')
+ mask = 2**self.bitdepth - 1
+ shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
+ for o in raw:
+ out.extend(map(lambda i: mask&(o>>i), shifts))
+ return out[:width]
+
+ return itertools.imap(asvalues, rows)
+
+ def serialtoflat(self, bytes, width=None):
+ """Convert serial format (byte stream) pixel data to flat row
+ flat pixel.
+ """
+
+ if self.bitdepth == 8:
+ return bytes
+ if self.bitdepth == 16:
+ bytes = tostring(bytes)
+ return array('H',
+ struct.unpack('!%dH' % (len(bytes)//2), bytes))
+ assert self.bitdepth < 8
+ if width is None:
+ width = self.width
+ # Samples per byte
+ spb = 8//self.bitdepth
+ out = array('B')
+ mask = 2**self.bitdepth - 1
+ shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
+ l = width
+ for o in bytes:
+ out.extend([(mask&(o>>s)) for s in shifts][:l])
+ l -= spb
+ if l <= 0:
+ l = width
+ return out
+
+ def iterstraight(self, raw):
+ """Iterator that undoes the effect of filtering, and yields each
+ row in serialised format (as a sequence of bytes). Assumes input
+ is straightlaced. `raw` should be an iterable that yields the
+ raw bytes in chunks of arbitrary size."""
+
+ # length of row, in bytes
+ rb = self.row_bytes
+ a = array('B')
+ # The previous (reconstructed) scanline. None indicates first
+ # line of image.
+ recon = None
+ for some in raw:
+ a.extend(some)
+ while len(a) >= rb + 1:
+ filter_type = a[0]
+ scanline = a[1:rb+1]
+ del a[:rb+1]
+ recon = self.undo_filter(filter_type, scanline, recon)
+ yield recon
+ if len(a) != 0:
+ # :file:format We get here with a file format error: when the
+ # available bytes (after decompressing) do not pack into exact
+ # rows.
+ raise FormatError(
+ 'Wrong size for decompressed IDAT chunk.')
+ assert len(a) == 0
+
+ def validate_signature(self):
+ """If signature (header) has not been read then read and
+ validate it; otherwise do nothing.
+ """
+
+ if self.signature:
+ return
+ self.signature = self.file.read(8)
+ if self.signature != _signature:
+ raise FormatError("PNG file has invalid signature.")
+
+ def preamble(self):
+ """
+ Extract the image metadata by reading the initial part of the PNG
+ file up to the start of the ``IDAT`` chunk. All the chunks that
+ precede the ``IDAT`` chunk are read and either processed for
+ metadata or discarded.
+ """
+
+ self.validate_signature()
+
+ while True:
+ if not self.atchunk:
+ self.atchunk = self.chunklentype()
+ if self.atchunk is None:
+ raise FormatError(
+ 'This PNG file has no IDAT chunks.')
+ if self.atchunk[1] == 'IDAT':
+ return
+ self.process_chunk()
+
+ def chunklentype(self):
+ """Reads just enough of the input to determine the next
+ chunk's length and type, returned as a (*length*, *type*) pair
+ where *type* is a string. If there are no more chunks, ``None``
+ is returned.
+ """
+
+ x = self.file.read(8)
+ if not x:
+ return None
+ if len(x) != 8:
+ raise FormatError(
+ 'End of file whilst reading chunk length and type.')
+ length,type = struct.unpack('!I4s', x)
+ type = bytestostr(type)
+ if length > 2**31-1:
+ raise FormatError('Chunk %s is too large: %d.' % (type,length))
+ return length,type
+
+ def process_chunk(self):
+ """Process the next chunk and its data. This only processes the
+ following chunk types, all others are ignored: ``IHDR``,
+ ``PLTE``, ``bKGD``, ``tRNS``, ``gAMA``, ``sBIT``.
+ """
+
+ type, data = self.chunk()
+ if type == 'IHDR':
+ # http://www.w3.org/TR/PNG/#11IHDR
+ if len(data) != 13:
+ raise FormatError('IHDR chunk has incorrect length.')
+ (self.width, self.height, self.bitdepth, self.color_type,
+ self.compression, self.filter,
+ self.interlace) = struct.unpack("!2I5B", data)
+
+ # Check that the header specifies only valid combinations.
+ if self.bitdepth not in (1,2,4,8,16):
+ raise Error("invalid bit depth %d" % self.bitdepth)
+ if self.color_type not in (0,2,3,4,6):
+ raise Error("invalid colour type %d" % self.color_type)
+ # Check indexed (palettized) images have 8 or fewer bits
+ # per pixel; check only indexed or greyscale images have
+ # fewer than 8 bits per pixel.
+ if ((self.color_type & 1 and self.bitdepth > 8) or
+ (self.bitdepth < 8 and self.color_type not in (0,3))):
+ raise FormatError("Illegal combination of bit depth (%d)"
+ " and colour type (%d)."
+ " See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
+ % (self.bitdepth, self.color_type))
+ if self.compression != 0:
+ raise Error("unknown compression method %d" % self.compression)
+ if self.filter != 0:
+ raise FormatError("Unknown filter method %d,"
+ " see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ."
+ % self.filter)
+ if self.interlace not in (0,1):
+ raise FormatError("Unknown interlace method %d,"
+ " see http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods ."
+ % self.interlace)
+
+ # Derived values
+ # http://www.w3.org/TR/PNG/#6Colour-values
+ colormap = bool(self.color_type & 1)
+ greyscale = not (self.color_type & 2)
+ alpha = bool(self.color_type & 4)
+ color_planes = (3,1)[greyscale or colormap]
+ planes = color_planes + alpha
+
+ self.colormap = colormap
+ self.greyscale = greyscale
+ self.alpha = alpha
+ self.color_planes = color_planes
+ self.planes = planes
+ self.psize = float(self.bitdepth)/float(8) * planes
+ if int(self.psize) == self.psize:
+ self.psize = int(self.psize)
+ self.row_bytes = int(math.ceil(self.width * self.psize))
+ # Stores PLTE chunk if present, and is used to check
+ # chunk ordering constraints.
+ self.plte = None
+ # Stores tRNS chunk if present, and is used to check chunk
+ # ordering constraints.
+ self.trns = None
+ # Stores sbit chunk if present.
+ self.sbit = None
+ elif type == 'PLTE':
+ # http://www.w3.org/TR/PNG/#11PLTE
+ if self.plte:
+ warnings.warn("Multiple PLTE chunks present.")
+ self.plte = data
+ if len(data) % 3 != 0:
+ raise FormatError(
+ "PLTE chunk's length should be a multiple of 3.")
+ if len(data) > (2**self.bitdepth)*3:
+ raise FormatError("PLTE chunk is too long.")
+ if len(data) == 0:
+ raise FormatError("Empty PLTE is not allowed.")
+ elif type == 'bKGD':
+ try:
+ if self.colormap:
+ if not self.plte:
+ warnings.warn(
+ "PLTE chunk is required before bKGD chunk.")
+ self.background = struct.unpack('B', data)
+ else:
+ self.background = struct.unpack("!%dH" % self.color_planes,
+ data)
+ except struct.error:
+ raise FormatError("bKGD chunk has incorrect length.")
+ elif type == 'tRNS':
+ # http://www.w3.org/TR/PNG/#11tRNS
+ self.trns = data
+ if self.colormap:
+ if not self.plte:
+ warnings.warn("PLTE chunk is required before tRNS chunk.")
+ else:
+ if len(data) > len(self.plte)/3:
+ # Was warning, but promoted to Error as it
+ # would otherwise cause pain later on.
+ raise FormatError("tRNS chunk is too long.")
+ else:
+ if self.alpha:
+ raise FormatError(
+ "tRNS chunk is not valid with colour type %d." %
+ self.color_type)
+ try:
+ self.transparent = \
+ struct.unpack("!%dH" % self.color_planes, data)
+ except struct.error:
+ raise FormatError("tRNS chunk has incorrect length.")
+ elif type == 'gAMA':
+ try:
+ self.gamma = struct.unpack("!L", data)[0] / 100000.0
+ except struct.error:
+ raise FormatError("gAMA chunk has incorrect length.")
+ elif type == 'sBIT':
+ self.sbit = data
+ if (self.colormap and len(data) != 3 or
+ not self.colormap and len(data) != self.planes):
+ raise FormatError("sBIT chunk has incorrect length.")
+
+ def read(self):
+ """
+ Read the PNG file and decode it. Returns (`width`, `height`,
+ `pixels`, `metadata`).
+
+ May use excessive memory.
+
+ `pixels` are returned in boxed row flat pixel format.
+ """
+
+ def iteridat():
+ """Iterator that yields all the ``IDAT`` chunks as strings."""
+ while True:
+ try:
+ type, data = self.chunk()
+ except ValueError, e:
+ raise ChunkError(e.args[0])
+ if type == 'IEND':
+ # http://www.w3.org/TR/PNG/#11IEND
+ break
+ if type != 'IDAT':
+ continue
+ # type == 'IDAT'
+ # http://www.w3.org/TR/PNG/#11IDAT
+ if self.colormap and not self.plte:
+ warnings.warn("PLTE chunk is required before IDAT chunk")
+ yield data
+
+ def iterdecomp(idat):
+ """Iterator that yields decompressed strings. `idat` should
+ be an iterator that yields the ``IDAT`` chunk data.
+ """
+
+ # Currently, with no max_length paramter to decompress, this
+ # routine will do one yield per IDAT chunk. So not very
+ # incremental.
+ d = zlib.decompressobj()
+ # Each IDAT chunk is passed to the decompressor, then any
+ # remaining state is decompressed out.
+ for data in idat:
+ # :todo: add a max_length argument here to limit output
+ # size.
+ yield array('B', d.decompress(data))
+ yield array('B', d.flush())
+
+ self.preamble()
+ raw = iterdecomp(iteridat())
+
+ if self.interlace:
+ raw = array('B', itertools.chain(*raw))
+ arraycode = 'BH'[self.bitdepth>8]
+ # Like :meth:`group` but producing an array.array object for
+ # each row.
+ pixels = itertools.imap(lambda *row: array(arraycode, row),
+ *[iter(self.deinterlace(raw))]*self.width*self.planes)
+ else:
+ pixels = self.iterboxed(self.iterstraight(raw))
+ meta = dict()
+ for attr in 'greyscale alpha planes bitdepth interlace'.split():
+ meta[attr] = getattr(self, attr)
+ meta['size'] = (self.width, self.height)
+ for attr in 'gamma transparent background'.split():
+ a = getattr(self, attr, None)
+ if a is not None:
+ meta[attr] = a
+ return self.width, self.height, pixels, meta
+
+
+ def read_flat(self):
+ """
+ Read a PNG file and decode it into flat row flat pixel format.
+ Returns (*width*, *height*, *pixels*, *metadata*).
+
+ May use excessive memory.
+
+ `pixels` are returned in flat row flat pixel format.
+
+ See also the :meth:`read` method which returns pixels in the
+ more stream-friendly boxed row flat pixel format.
+ """
+
+ x, y, pixel, meta = self.read()
+ arraycode = 'BH'[meta['bitdepth']>8]
+ pixel = array(arraycode, itertools.chain(*pixel))
+ return x, y, pixel, meta
+
+ def palette(self, alpha='natural'):
+ """Returns a palette that is a sequence of 3-tuples or 4-tuples,
+ synthesizing it from the ``PLTE`` and ``tRNS`` chunks. These
+ chunks should have already been processed (for example, by
+ calling the :meth:`preamble` method). All the tuples are the
+ same size: 3-tuples if there is no ``tRNS`` chunk, 4-tuples when
+ there is a ``tRNS`` chunk. Assumes that the image is colour type
+ 3 and therefore a ``PLTE`` chunk is required.
+
+ If the `alpha` argument is ``'force'`` then an alpha channel is
+ always added, forcing the result to be a sequence of 4-tuples.
+ """
+
+ if not self.plte:
+ raise FormatError(
+ "Required PLTE chunk is missing in colour type 3 image.")
+ plte = group(array('B', self.plte), 3)
+ if self.trns or alpha == 'force':
+ trns = array('B', self.trns or '')
+ trns.extend([255]*(len(plte)-len(trns)))
+ plte = map(operator.add, plte, group(trns, 1))
+ return plte
+
+ def asDirect(self):
+ """Returns the image data as a direct representation of an
+ ``x * y * planes`` array. This method is intended to remove the
+ need for callers to deal with palettes and transparency
+ themselves. Images with a palette (colour type 3)
+ are converted to RGB or RGBA; images with transparency (a
+ ``tRNS`` chunk) are converted to LA or RGBA as appropriate.
+ When returned in this format the pixel values represent the
+ colour value directly without needing to refer to palettes or
+ transparency information.
+
+ Like the :meth:`read` method this method returns a 4-tuple:
+
+ (*width*, *height*, *pixels*, *meta*)
+
+ This method normally returns pixel values with the bit depth
+ they have in the source image, but when the source PNG has an
+ ``sBIT`` chunk it is inspected and can reduce the bit depth of
+ the result pixels; pixel values will be reduced according to
+ the bit depth specified in the ``sBIT`` chunk (PNG nerds should
+ note a single result bit depth is used for all channels; the
+ maximum of the ones specified in the ``sBIT`` chunk. An RGB565
+ image will be rescaled to 6-bit RGB666).
+
+ The *meta* dictionary that is returned reflects the `direct`
+ format and not the original source image. For example, an RGB
+ source image with a ``tRNS`` chunk to represent a transparent
+ colour, will have ``planes=3`` and ``alpha=False`` for the
+ source image, but the *meta* dictionary returned by this method
+ will have ``planes=4`` and ``alpha=True`` because an alpha
+ channel is synthesized and added.
+
+ *pixels* is the pixel data in boxed row flat pixel format (just
+ like the :meth:`read` method).
+
+ All the other aspects of the image data are not changed.
+ """
+
+ self.preamble()
+
+ # Simple case, no conversion necessary.
+ if not self.colormap and not self.trns and not self.sbit:
+ return self.read()
+
+ x,y,pixels,meta = self.read()
+
+ if self.colormap:
+ meta['colormap'] = False
+ meta['alpha'] = bool(self.trns)
+ meta['bitdepth'] = 8
+ meta['planes'] = 3 + bool(self.trns)
+ plte = self.palette()
+ def iterpal(pixels):
+ for row in pixels:
+ row = map(plte.__getitem__, row)
+ yield array('B', itertools.chain(*row))
+ pixels = iterpal(pixels)
+ elif self.trns:
+ # It would be nice if there was some reasonable way of doing
+ # this without generating a whole load of intermediate tuples.
+ # But tuples does seem like the easiest way, with no other way
+ # clearly much simpler or much faster. (Actually, the L to LA
+ # conversion could perhaps go faster (all those 1-tuples!), but
+ # I still wonder whether the code proliferation is worth it)
+ it = self.transparent
+ maxval = 2**meta['bitdepth']-1
+ planes = meta['planes']
+ meta['alpha'] = True
+ meta['planes'] += 1
+ typecode = 'BH'[meta['bitdepth']>8]
+ def itertrns(pixels):
+ for row in pixels:
+ # For each row we group it into pixels, then form a
+ # characterisation vector that says whether each pixel
+ # is opaque or not. Then we convert True/False to
+ # 0/maxval (by multiplication), and add it as the extra
+ # channel.
+ row = group(row, planes)
+ opa = map(it.__ne__, row)
+ opa = map(maxval.__mul__, opa)
+ opa = zip(opa) # convert to 1-tuples
+ yield array(typecode,
+ itertools.chain(*map(operator.add, row, opa)))
+ pixels = itertrns(pixels)
+ targetbitdepth = None
+ if self.sbit:
+ sbit = struct.unpack('%dB' % len(self.sbit), self.sbit)
+ targetbitdepth = max(sbit)
+ if targetbitdepth > meta['bitdepth']:
+ raise Error('sBIT chunk %r exceeds bitdepth %d' %
+ (sbit,self.bitdepth))
+ if min(sbit) <= 0:
+ raise Error('sBIT chunk %r has a 0-entry' % sbit)
+ if targetbitdepth == meta['bitdepth']:
+ targetbitdepth = None
+ if targetbitdepth:
+ shift = meta['bitdepth'] - targetbitdepth
+ meta['bitdepth'] = targetbitdepth
+ def itershift(pixels):
+ for row in pixels:
+ yield map(shift.__rrshift__, row)
+ pixels = itershift(pixels)
+ return x,y,pixels,meta
+
+ def asFloat(self, maxval=1.0):
+ """Return image pixels as per :meth:`asDirect` method, but scale
+ all pixel values to be floating point values between 0.0 and
+ *maxval*.
+ """
+
+ x,y,pixels,info = self.asDirect()
+ sourcemaxval = 2**info['bitdepth']-1
+ del info['bitdepth']
+ info['maxval'] = float(maxval)
+ factor = float(maxval)/float(sourcemaxval)
+ def iterfloat():
+ for row in pixels:
+ yield map(factor.__mul__, row)
+ return x,y,iterfloat(),info
+
+ def _as_rescale(self, get, targetbitdepth):
+ """Helper used by :meth:`asRGB8` and :meth:`asRGBA8`."""
+
+ width,height,pixels,meta = get()
+ maxval = 2**meta['bitdepth'] - 1
+ targetmaxval = 2**targetbitdepth - 1
+ factor = float(targetmaxval) / float(maxval)
+ meta['bitdepth'] = targetbitdepth
+ def iterscale():
+ for row in pixels:
+ yield map(lambda x: int(round(x*factor)), row)
+ return width, height, iterscale(), meta
+
+ def asRGB8(self):
+ """Return the image data as an RGB pixels with 8-bits per
+ sample. This is like the :meth:`asRGB` method except that
+ this method additionally rescales the values so that they
+ are all between 0 and 255 (8-bit). In the case where the
+ source image has a bit depth < 8 the transformation preserves
+ all the information; where the source image has bit depth
+ > 8, then rescaling to 8-bit values loses precision. No
+ dithering is performed. Like :meth:`asRGB`, an alpha channel
+ in the source image will raise an exception.
+
+ This function returns a 4-tuple:
+ (*width*, *height*, *pixels*, *metadata*).
+ *width*, *height*, *metadata* are as per the :meth:`read` method.
+
+ *pixels* is the pixel data in boxed row flat pixel format.
+ """
+
+ return self._as_rescale(self.asRGB, 8)
+
+ def asRGBA8(self):
+ """Return the image data as RGBA pixels with 8-bits per
+ sample. This method is similar to :meth:`asRGB8` and
+ :meth:`asRGBA`: The result pixels have an alpha channel, *and*
+ values are rescaled to the range 0 to 255. The alpha channel is
+ synthesized if necessary (with a small speed penalty).
+ """
+
+ return self._as_rescale(self.asRGBA, 8)
+
+ def asRGB(self):
+ """Return image as RGB pixels. RGB colour images are passed
+ through unchanged; greyscales are expanded into RGB
+ triplets (there is a small speed overhead for doing this).
+
+ An alpha channel in the source image will raise an
+ exception.
+
+ The return values are as for the :meth:`read` method
+ except that the *metadata* reflect the returned pixels, not the
+ source image. In particular, for this method
+ ``metadata['greyscale']`` will be ``False``.
+ """
+
+ width,height,pixels,meta = self.asDirect()
+ if meta['alpha']:
+ raise Error("will not convert image with alpha channel to RGB")
+ if not meta['greyscale']:
+ return width,height,pixels,meta
+ meta['greyscale'] = False
+ typecode = 'BH'[meta['bitdepth'] > 8]
+ def iterrgb():
+ for row in pixels:
+ a = array(typecode, [0]) * 3 * width
+ for i in range(3):
+ a[i::3] = row
+ yield a
+ return width,height,iterrgb(),meta
+
+ def asRGBA(self):
+ """Return image as RGBA pixels. Greyscales are expanded into
+ RGB triplets; an alpha channel is synthesized if necessary.
+ The return values are as for the :meth:`read` method
+ except that the *metadata* reflect the returned pixels, not the
+ source image. In particular, for this method
+ ``metadata['greyscale']`` will be ``False``, and
+ ``metadata['alpha']`` will be ``True``.
+ """
+
+ width,height,pixels,meta = self.asDirect()
+ if meta['alpha'] and not meta['greyscale']:
+ return width,height,pixels,meta
+ typecode = 'BH'[meta['bitdepth'] > 8]
+ maxval = 2**meta['bitdepth'] - 1
+ def newarray():
+ return array(typecode, [0]) * 4 * width
+ if meta['alpha'] and meta['greyscale']:
+ # LA to RGBA
+ def convert():
+ for row in pixels:
+ # Create a fresh target row, then copy L channel
+ # into first three target channels, and A channel
+ # into fourth channel.
+ a = newarray()
+ for i in range(3):
+ a[i::4] = row[0::2]
+ a[3::4] = row[1::2]
+ yield a
+ elif meta['greyscale']:
+ # L to RGBA
+ def convert():
+ for row in pixels:
+ a = newarray()
+ for i in range(3):
+ a[i::4] = row
+ a[3::4] = array(typecode, [maxval]) * width
+ yield a
+ else:
+ assert not meta['alpha'] and not meta['greyscale']
+ # RGB to RGBA
+ def convert():
+ for row in pixels:
+ a = newarray()
+ for i in range(3):
+ a[i::4] = row[i::3]
+ a[3::4] = array(typecode, [maxval]) * width
+ yield a
+ meta['alpha'] = True
+ meta['greyscale'] = False
+ return width,height,convert(),meta
+
+
+# === Legacy Version Support ===
+
+# :pyver:old: PyPNG works on Python versions 2.3 and 2.2, but not
+# without some awkward problems. Really PyPNG works on Python 2.4 (and
+# above); it works on Pythons 2.3 and 2.2 by virtue of fixing up
+# problems here. It's a bit ugly (which is why it's hidden down here).
+#
+# Generally the strategy is one of pretending that we're running on
+# Python 2.4 (or above), and patching up the library support on earlier
+# versions so that it looks enough like Python 2.4. When it comes to
+# Python 2.2 there is one thing we cannot patch: extended slices
+# http://www.python.org/doc/2.3/whatsnew/section-slices.html.
+# Instead we simply declare that features that are implemented using
+# extended slices will not work on Python 2.2.
+#
+# In order to work on Python 2.3 we fix up a recurring annoyance involving
+# the array type. In Python 2.3 an array cannot be initialised with an
+# array, and it cannot be extended with a list (or other sequence).
+# Both of those are repeated issues in the code. Whilst I would not
+# normally tolerate this sort of behaviour, here we "shim" a replacement
+# for array into place (and hope no-ones notices). You never read this.
+#
+# In an amusing case of warty hacks on top of warty hacks... the array
+# shimming we try and do only works on Python 2.3 and above (you can't
+# subclass array.array in Python 2.2). So to get it working on Python
+# 2.2 we go for something much simpler and (probably) way slower.
+try:
+ array('B').extend([])
+ array('B', array('B'))
+except:
+ # Expect to get here on Python 2.3
+ try:
+ class _array_shim(array):
+ true_array = array
+ def __new__(cls, typecode, init=None):
+ super_new = super(_array_shim, cls).__new__
+ it = super_new(cls, typecode)
+ if init is None:
+ return it
+ it.extend(init)
+ return it
+ def extend(self, extension):
+ super_extend = super(_array_shim, self).extend
+ if isinstance(extension, self.true_array):
+ return super_extend(extension)
+ if not isinstance(extension, (list, str)):
+ # Convert to list. Allows iterators to work.
+ extension = list(extension)
+ return super_extend(self.true_array(self.typecode, extension))
+ array = _array_shim
+ except:
+ # Expect to get here on Python 2.2
+ def array(typecode, init=()):
+ if type(init) == str:
+ return map(ord, init)
+ return list(init)
+
+# Further hacks to get it limping along on Python 2.2
+try:
+ enumerate
+except:
+ def enumerate(seq):
+ i=0
+ for x in seq:
+ yield i,x
+ i += 1
+
+try:
+ reversed
+except:
+ def reversed(l):
+ l = list(l)
+ l.reverse()
+ for x in l:
+ yield x
+
+try:
+ itertools
+except:
+ class _dummy_itertools:
+ pass
+ itertools = _dummy_itertools()
+ def _itertools_imap(f, seq):
+ for x in seq:
+ yield f(x)
+ itertools.imap = _itertools_imap
+ def _itertools_chain(*iterables):
+ for it in iterables:
+ for element in it:
+ yield element
+ itertools.chain = _itertools_chain
+
+
+
+# === Internal Test Support ===
+
+# This section comprises the tests that are internally validated (as
+# opposed to tests which produce output files that are externally
+# validated). Primarily they are unittests.
+
+# Note that it is difficult to internally validate the results of
+# writing a PNG file. The only thing we can do is read it back in
+# again, which merely checks consistency, not that the PNG file we
+# produce is valid.
+
+# Run the tests from the command line:
+# python -c 'import png;png.test()'
+
+# (For an in-memory binary file IO object) We use BytesIO where
+# available, otherwise we use StringIO, but name it BytesIO.
+try:
+ from io import BytesIO
+except:
+ from StringIO import StringIO as BytesIO
+import tempfile
+# http://www.python.org/doc/2.4.4/lib/module-unittest.html
+import unittest
+
+
+def test():
+ unittest.main(__name__)
+
+def topngbytes(name, rows, x, y, **k):
+ """Convenience function for creating a PNG file "in memory" as a
+ string. Creates a :class:`Writer` instance using the keyword arguments,
+ then passes `rows` to its :meth:`Writer.write` method. The resulting
+ PNG file is returned as a string. `name` is used to identify the file for
+ debugging.
+ """
+
+ import os
+
+ print name
+ f = BytesIO()
+ w = Writer(x, y, **k)
+ w.write(f, rows)
+ if os.environ.get('PYPNG_TEST_TMP'):
+ w = open(name, 'wb')
+ w.write(f.getvalue())
+ w.close()
+ return f.getvalue()
+
+def testWithIO(inp, out, f):
+ """Calls the function `f` with ``sys.stdin`` changed to `inp`
+ and ``sys.stdout`` changed to `out`. They are restored when `f`
+ returns. This function returns whatever `f` returns.
+ """
+
+ import os
+
+ try:
+ oldin,sys.stdin = sys.stdin,inp
+ oldout,sys.stdout = sys.stdout,out
+ x = f()
+ finally:
+ sys.stdin = oldin
+ sys.stdout = oldout
+ if os.environ.get('PYPNG_TEST_TMP') and hasattr(out,'getvalue'):
+ name = mycallersname()
+ if name:
+ w = open(name+'.png', 'wb')
+ w.write(out.getvalue())
+ w.close()
+ return x
+
+def mycallersname():
+ """Returns the name of the caller of the caller of this function
+ (hence the name of the caller of the function in which
+ "mycallersname()" textually appears). Returns None if this cannot
+ be determined."""
+
+ # http://docs.python.org/library/inspect.html#the-interpreter-stack
+ import inspect
+
+ frame = inspect.currentframe()
+ if not frame:
+ return None
+ frame_,filename_,lineno_,funname,linelist_,listi_ = (
+ inspect.getouterframes(frame)[2])
+ return funname
+
+def seqtobytes(s):
+ """Convert a sequence of integers to a *bytes* instance. Good for
+ plastering over Python 2 / Python 3 cracks.
+ """
+
+ return strtobytes(''.join(chr(x) for x in s))
+
+class Test(unittest.TestCase):
+ # This member is used by the superclass. If we don't define a new
+ # class here then when we use self.assertRaises() and the PyPNG code
+ # raises an assertion then we get no proper traceback. I can't work
+ # out why, but defining a new class here means we get a proper
+ # traceback.
+ class failureException(Exception):
+ pass
+
+ def helperLN(self, n):
+ mask = (1 << n) - 1
+ # Use small chunk_limit so that multiple chunk writing is
+ # tested. Making it a test for Issue 20.
+ w = Writer(15, 17, greyscale=True, bitdepth=n, chunk_limit=99)
+ f = BytesIO()
+ w.write_array(f, array('B', map(mask.__and__, range(1, 256))))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertEqual(x, 15)
+ self.assertEqual(y, 17)
+ self.assertEqual(list(itertools.chain(*pixels)),
+ map(mask.__and__, range(1,256)))
+ def testL8(self):
+ return self.helperLN(8)
+ def testL4(self):
+ return self.helperLN(4)
+ def testL2(self):
+ "Also tests asRGB8."
+ w = Writer(1, 4, greyscale=True, bitdepth=2)
+ f = BytesIO()
+ w.write_array(f, array('B', range(4)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGB8()
+ self.assertEqual(x, 1)
+ self.assertEqual(y, 4)
+ for i,row in enumerate(pixels):
+ self.assertEqual(len(row), 3)
+ self.assertEqual(list(row), [0x55*i]*3)
+ def testP2(self):
+ "2-bit palette."
+ a = (255,255,255)
+ b = (200,120,120)
+ c = (50,99,50)
+ w = Writer(1, 4, bitdepth=2, palette=[a,b,c])
+ f = BytesIO()
+ w.write_array(f, array('B', (0,1,1,2)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGB8()
+ self.assertEqual(x, 1)
+ self.assertEqual(y, 4)
+ self.assertEqual(list(pixels), map(list, [a, b, b, c]))
+ def testPtrns(self):
+ "Test colour type 3 and tRNS chunk (and 4-bit palette)."
+ a = (50,99,50,50)
+ b = (200,120,120,80)
+ c = (255,255,255)
+ d = (200,120,120)
+ e = (50,99,50)
+ w = Writer(3, 3, bitdepth=4, palette=[a,b,c,d,e])
+ f = BytesIO()
+ w.write_array(f, array('B', (4, 3, 2, 3, 2, 0, 2, 0, 1)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGBA8()
+ self.assertEqual(x, 3)
+ self.assertEqual(y, 3)
+ c = c+(255,)
+ d = d+(255,)
+ e = e+(255,)
+ boxed = [(e,d,c),(d,c,a),(c,a,b)]
+ flat = map(lambda row: itertools.chain(*row), boxed)
+ self.assertEqual(map(list, pixels), map(list, flat))
+ def testRGBtoRGBA(self):
+ "asRGBA8() on colour type 2 source."""
+ # Test for Issue 26
+ r = Reader(bytes=_pngsuite['basn2c08'])
+ x,y,pixels,meta = r.asRGBA8()
+ # Test the pixels at row 9 columns 0 and 1.
+ row9 = list(pixels)[9]
+ self.assertEqual(row9[0:8],
+ [0xff, 0xdf, 0xff, 0xff, 0xff, 0xde, 0xff, 0xff])
+ def testLtoRGBA(self):
+ "asRGBA() on grey source."""
+ # Test for Issue 60
+ r = Reader(bytes=_pngsuite['basi0g08'])
+ x,y,pixels,meta = r.asRGBA()
+ row9 = list(list(pixels)[9])
+ self.assertEqual(row9[0:8],
+ [222, 222, 222, 255, 221, 221, 221, 255])
+ def testCtrns(self):
+ "Test colour type 2 and tRNS chunk."
+ # Test for Issue 25
+ r = Reader(bytes=_pngsuite['tbrn2c08'])
+ x,y,pixels,meta = r.asRGBA8()
+ # I just happen to know that the first pixel is transparent.
+ # In particular it should be #7f7f7f00
+ row0 = list(pixels)[0]
+ self.assertEqual(tuple(row0[0:4]), (0x7f, 0x7f, 0x7f, 0x00))
+ def testAdam7read(self):
+ """Adam7 interlace reading.
+ Specifically, test that for images in the PngSuite that
+ have both an interlaced and straightlaced pair that both
+ images from the pair produce the same array of pixels."""
+ for candidate in _pngsuite:
+ if not candidate.startswith('basn'):
+ continue
+ candi = candidate.replace('n', 'i')
+ if candi not in _pngsuite:
+ continue
+ print 'adam7 read', candidate
+ straight = Reader(bytes=_pngsuite[candidate])
+ adam7 = Reader(bytes=_pngsuite[candi])
+ # Just compare the pixels. Ignore x,y (because they're
+ # likely to be correct?); metadata is ignored because the
+ # "interlace" member differs. Lame.
+ straight = straight.read()[2]
+ adam7 = adam7.read()[2]
+ self.assertEqual(map(list, straight), map(list, adam7))
+ def testAdam7write(self):
+ """Adam7 interlace writing.
+ For each test image in the PngSuite, write an interlaced
+ and a straightlaced version. Decode both, and compare results.
+ """
+ # Not such a great test, because the only way we can check what
+ # we have written is to read it back again.
+
+ for name,bytes in _pngsuite.items():
+ # Only certain colour types supported for this test.
+ if name[3:5] not in ['n0', 'n2', 'n4', 'n6']:
+ continue
+ it = Reader(bytes=bytes)
+ x,y,pixels,meta = it.read()
+ pngi = topngbytes('adam7wn'+name+'.png', pixels,
+ x=x, y=y, bitdepth=it.bitdepth,
+ greyscale=it.greyscale, alpha=it.alpha,
+ transparent=it.transparent,
+ interlace=False)
+ x,y,ps,meta = Reader(bytes=pngi).read()
+ it = Reader(bytes=bytes)
+ x,y,pixels,meta = it.read()
+ pngs = topngbytes('adam7wi'+name+'.png', pixels,
+ x=x, y=y, bitdepth=it.bitdepth,
+ greyscale=it.greyscale, alpha=it.alpha,
+ transparent=it.transparent,
+ interlace=True)
+ x,y,pi,meta = Reader(bytes=pngs).read()
+ self.assertEqual(map(list, ps), map(list, pi))
+ def testPGMin(self):
+ """Test that the command line tool can read PGM files."""
+ def do():
+ return _main(['testPGMin'])
+ s = BytesIO()
+ s.write(strtobytes('P5 2 2 3\n'))
+ s.write(strtobytes('\x00\x01\x02\x03'))
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertTrue(r.greyscale)
+ self.assertEqual(r.bitdepth, 2)
+ def testPAMin(self):
+ """Test that the command line tool can read PAM file."""
+ def do():
+ return _main(['testPAMin'])
+ s = BytesIO()
+ s.write(strtobytes('P7\nWIDTH 3\nHEIGHT 1\nDEPTH 4\nMAXVAL 255\n'
+ 'TUPLTYPE RGB_ALPHA\nENDHDR\n'))
+ # The pixels in flat row flat pixel format
+ flat = [255,0,0,255, 0,255,0,120, 0,0,255,30]
+ asbytes = seqtobytes(flat)
+ s.write(asbytes)
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertTrue(r.alpha)
+ self.assertTrue(not r.greyscale)
+ self.assertEqual(list(itertools.chain(*pixels)), flat)
+ def testLA4(self):
+ """Create an LA image with bitdepth 4."""
+ bytes = topngbytes('la4.png', [[5, 12]], 1, 1,
+ greyscale=True, alpha=True, bitdepth=4)
+ sbit = Reader(bytes=bytes).chunk('sBIT')[1]
+ self.assertEqual(sbit, strtobytes('\x04\x04'))
+ def testPNMsbit(self):
+ """Test that PNM files can generates sBIT chunk."""
+ def do():
+ return _main(['testPNMsbit'])
+ s = BytesIO()
+ s.write(strtobytes('P6 8 1 1\n'))
+ for pixel in range(8):
+ s.write(struct.pack('<I', (0x4081*pixel)&0x10101)[:3])
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ sbit = r.chunk('sBIT')[1]
+ self.assertEqual(sbit, strtobytes('\x01\x01\x01'))
+ def testLtrns0(self):
+ """Create greyscale image with tRNS chunk."""
+ return self.helperLtrns(0)
+ def testLtrns1(self):
+ """Using 1-tuple for transparent arg."""
+ return self.helperLtrns((0,))
+ def helperLtrns(self, transparent):
+ """Helper used by :meth:`testLtrns*`."""
+ pixels = zip([0x00, 0x38, 0x4c, 0x54, 0x5c, 0x40, 0x38, 0x00])
+ o = BytesIO()
+ w = Writer(8, 8, greyscale=True, bitdepth=1, transparent=transparent)
+ w.write_packed(o, pixels)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.asDirect()
+ self.assertTrue(meta['alpha'])
+ self.assertTrue(meta['greyscale'])
+ self.assertEqual(meta['bitdepth'], 1)
+ def testWinfo(self):
+ """Test the dictionary returned by a `read` method can be used
+ as args for :meth:`Writer`.
+ """
+ r = Reader(bytes=_pngsuite['basn2c16'])
+ info = r.read()[3]
+ w = Writer(**info)
+ def testPackedIter(self):
+ """Test iterator for row when using write_packed.
+
+ Indicative for Issue 47.
+ """
+ w = Writer(16, 2, greyscale=True, alpha=False, bitdepth=1)
+ o = BytesIO()
+ w.write_packed(o, [itertools.chain([0x0a], [0xaa]),
+ itertools.chain([0x0f], [0xff])])
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,info = r.asDirect()
+ pixels = list(pixels)
+ self.assertEqual(len(pixels), 2)
+ self.assertEqual(len(pixels[0]), 16)
+ def testInterlacedArray(self):
+ """Test that reading an interlaced PNG yields each row as an
+ array."""
+ r = Reader(bytes=_pngsuite['basi0g08'])
+ list(r.read()[2])[0].tostring
+ def testTrnsArray(self):
+ """Test that reading a type 2 PNG with tRNS chunk yields each
+ row as an array (using asDirect)."""
+ r = Reader(bytes=_pngsuite['tbrn2c08'])
+ list(r.asDirect()[2])[0].tostring
+
+ # Invalid file format tests. These construct various badly
+ # formatted PNG files, then feed them into a Reader. When
+ # everything is working properly, we should get FormatError
+ # exceptions raised.
+ def testEmpty(self):
+ """Test empty file."""
+
+ r = Reader(bytes='')
+ self.assertRaises(FormatError, r.asDirect)
+ def testSigOnly(self):
+ """Test file containing just signature bytes."""
+
+ r = Reader(bytes=_signature)
+ self.assertRaises(FormatError, r.asDirect)
+ def testExtraPixels(self):
+ """Test file that contains too many pixels."""
+
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ data = zlib.decompress(chunk[1])
+ data += strtobytes('\x00garbage')
+ data = zlib.compress(data)
+ chunk = (chunk[0], data)
+ return chunk
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+ def testNotEnoughPixels(self):
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ # Remove last byte.
+ data = zlib.decompress(chunk[1])
+ data = data[:-1]
+ data = zlib.compress(data)
+ return (chunk[0], data)
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+ def helperFormat(self, f):
+ r = Reader(bytes=_pngsuite['basn0g01'])
+ o = BytesIO()
+ def newchunks():
+ for chunk in r.chunks():
+ yield f(chunk)
+ write_chunks(o, newchunks())
+ r = Reader(bytes=o.getvalue())
+ return list(r.asDirect()[2])
+ def testBadFilter(self):
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ data = zlib.decompress(chunk[1])
+ # Corrupt the first filter byte
+ data = strtobytes('\x99') + data[1:]
+ data = zlib.compress(data)
+ return (chunk[0], data)
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+ def testFlat(self):
+ """Test read_flat."""
+ import hashlib
+
+ r = Reader(bytes=_pngsuite['basn0g02'])
+ x,y,pixel,meta = r.read_flat()
+ d = hashlib.md5(seqtobytes(pixel)).digest()
+ self.assertEqual(_enhex(d), '255cd971ab8cd9e7275ff906e5041aa0')
+ def testfromarray(self):
+ img = from_array([[0, 0x33, 0x66], [0xff, 0xcc, 0x99]], 'L')
+ img.save('testfromarray.png')
+ def testfromarrayL16(self):
+ img = from_array(group(range(2**16), 256), 'L;16')
+ img.save('testL16.png')
+ def testfromarrayRGB(self):
+ img = from_array([[0,0,0, 0,0,1, 0,1,0, 0,1,1],
+ [1,0,0, 1,0,1, 1,1,0, 1,1,1]], 'RGB;1')
+ o = BytesIO()
+ img.save(o)
+ def testfromarrayIter(self):
+ import itertools
+
+ i = itertools.islice(itertools.count(10), 20)
+ i = itertools.imap(lambda x: [x, x, x], i)
+ img = from_array(i, 'RGB;5', dict(height=20))
+ f = open('testiter.png', 'wb')
+ img.save(f)
+ f.close()
+
+ # numpy dependent tests. These are skipped (with a message to
+ # sys.stderr) if numpy cannot be imported.
+ def testNumpyuint16(self):
+ """numpy uint16."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.uint16, range(0,0x10000,0x5555))]
+ b = topngbytes('numpyuint16.png', rows, 4, 1,
+ greyscale=True, alpha=False, bitdepth=16)
+ def testNumpyuint8(self):
+ """numpy uint8."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.uint8, range(0,0x100,0x55))]
+ b = topngbytes('numpyuint8.png', rows, 4, 1,
+ greyscale=True, alpha=False, bitdepth=8)
+ def testNumpybool(self):
+ """numpy bool."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.bool, [0,1])]
+ b = topngbytes('numpybool.png', rows, 2, 1,
+ greyscale=True, alpha=False, bitdepth=1)
+ def testNumpyarray(self):
+ """numpy array."""
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ pixels = numpy.array([[0,0x5555],[0x5555,0xaaaa]], numpy.uint16)
+ img = from_array(pixels, 'L')
+ img.save('testnumpyL16.png')
+
+# === Command Line Support ===
+
+def _dehex(s):
+ """Liberally convert from hex string to binary string."""
+ import re
+ import binascii
+
+ # Remove all non-hexadecimal digits
+ s = re.sub(r'[^a-fA-F\d]', '', s)
+ # binscii.unhexlify works in Python 2 and Python 3 (unlike
+ # thing.decode('hex')).
+ return binascii.unhexlify(strtobytes(s))
+def _enhex(s):
+ """Convert from binary string (bytes) to hex string (str)."""
+
+ import binascii
+
+ return bytestostr(binascii.hexlify(s))
+
+# Copies of PngSuite test files taken
+# from http://www.schaik.com/pngsuite/pngsuite_bas_png.html
+# on 2009-02-19 by drj and converted to hex.
+# Some of these are not actually in PngSuite (but maybe they should
+# be?), they use the same naming scheme, but start with a capital
+# letter.
+_pngsuite = {
+ 'basi0g01': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002001000000012c0677
+cf0000000467414d41000186a031e8965f0000009049444154789c2d8d310ec2
+300c45dfc682c415187a00a42e197ab81e83b127e00c5639001363a580d8582c
+65c910357c4b78b0bfbfdf4f70168c19e7acb970a3f2d1ded9695ce5bf5963df
+d92aaf4c9fd927ea449e6487df5b9c36e799b91bdf082b4d4bd4014fe4014b01
+ab7a17aee694d28d328a2d63837a70451e1648702d9a9ff4a11d2f7a51aa21e5
+a18c7ffd0094e3511d661822f20000000049454e44ae426082
+"""),
+ 'basi0g02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002002000000016ba60d
+1f0000000467414d41000186a031e8965f0000005149444154789c635062e860
+00e17286bb609c93c370ec189494960631366e4467b3ae675dcf10f521ea0303
+90c1ca006444e11643482064114a4852c710baea3f18c31918020c30410403a6
+0ac1a09239009c52804d85b6d97d0000000049454e44ae426082
+"""),
+ 'basi0g04': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200400000001e4e6f8
+bf0000000467414d41000186a031e8965f000000ae49444154789c658e5111c2
+301044171c141c141c041c843a287510ea20d441c041c141c141c04191102454
+03994998cecd7edcecedbb9bdbc3b2c2b6457545fbc4bac1be437347f7c66a77
+3c23d60db15e88f5c5627338a5416c2e691a9b475a89cd27eda12895ae8dfdab
+43d61e590764f5c83a226b40d669bec307f93247701687723abf31ff83a2284b
+a5b4ae6b63ac6520ad730ca4ed7b06d20e030369bd6720ed383290360406d24e
+13811f2781eba9d34d07160000000049454e44ae426082
+"""),
+ 'basi0g08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200800000001211615
+be0000000467414d41000186a031e8965f000000b549444154789cb5905d0ac2
+3010849dbac81c42c47bf843cf253e8878b0aa17110f214bdca6be240f5d21a5
+94ced3e49bcd322c1624115515154998aa424822a82a5624a1aa8a8b24c58f99
+999908130989a04a00d76c2c09e76cf21adcb209393a6553577da17140a2c59e
+70ecbfa388dff1f03b82fb82bd07f05f7cb13f80bb07ad2fd60c011c3c588eef
+f1f4e03bbec7ce832dca927aea005e431b625796345307b019c845e6bfc3bb98
+769d84f9efb02ea6c00f9bb9ff45e81f9f280000000049454e44ae426082
+"""),
+ 'basi0g16': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002010000000017186c9
+fd0000000467414d41000186a031e8965f000000e249444154789cb5913b0ec2
+301044c7490aa8f85d81c3e4301c8f53a4ca0da8902c8144b3920b4043111282
+23bc4956681a6bf5fc3c5a3ba0448912d91a4de2c38dd8e380231eede4c4f7a1
+4677700bec7bd9b1d344689315a3418d1a6efbe5b8305ba01f8ff4808c063e26
+c60d5c81edcf6c58c535e252839e93801b15c0a70d810ae0d306b205dc32b187
+272b64057e4720ff0502154034831520154034c3df81400510cdf0015c86e5cc
+5c79c639fddba9dcb5456b51d7980eb52d8e7d7fa620a75120d6064641a05120
+b606771a05626b401a05f1f589827cf0fe44c1f0bae0055698ee8914fffffe00
+00000049454e44ae426082
+"""),
+ 'basi2c08': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002008020000018b1fdd
+350000000467414d41000186a031e8965f000000f249444154789cd59341aa04
+210c44abc07b78133d59d37333bd89d76868b566d10cf4675af8596431a11662
+7c5688919280e312257dd6a0a4cf1a01008ee312a5f3c69c37e6fcc3f47e6776
+a07f8bdaf5b40feed2d33e025e2ff4fe2d4a63e1a16d91180b736d8bc45854c5
+6d951863f4a7e0b66dcf09a900f3ffa2948d4091e53ca86c048a64390f662b50
+4a999660ced906182b9a01a8be00a56404a6ede182b1223b4025e32c4de34304
+63457680c93aada6c99b73865aab2fc094920d901a203f5ddfe1970d28456783
+26cffbafeffcd30654f46d119be4793f827387fc0d189d5bc4d69a3c23d45a7f
+db803146578337df4d0a3121fc3d330000000049454e44ae426082
+"""),
+ 'basi2c16': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000201002000001db8f01
+760000000467414d41000186a031e8965f0000020a49444154789cd5962173e3
+3010853fcf1838cc61a1818185a53e56787fa13fa130852e3b5878b4b0b03081
+b97f7030070b53e6b057a0a8912bbb9163b9f109ececbc59bd7dcf2b45492409
+d66f00eb1dd83cb5497d65456aeb8e1040913b3b2c04504c936dd5a9c7e2c6eb
+b1b8f17a58e8d043da56f06f0f9f62e5217b6ba3a1b76f6c9e99e8696a2a72e2
+c4fb1e4d452e92ec9652b807486d12b6669be00db38d9114b0c1961e375461a5
+5f76682a85c367ad6f682ff53a9c2a353191764b78bb07d8ddc3c97c1950f391
+6745c7b9852c73c2f212605a466a502705c8338069c8b9e84efab941eb393a97
+d4c9fd63148314209f1c1d3434e847ead6380de291d6f26a25c1ebb5047f5f24
+d85c49f0f22cc1d34282c72709cab90477bf25b89d49f0f351822297e0ea9704
+f34c82bc94002448ede51866e5656aef5d7c6a385cb4d80e6a538ceba04e6df2
+480e9aa84ddedb413bb5c97b3838456df2d4fec2c7a706983e7474d085fae820
+a841776a83073838973ac0413fea2f1dc4a06e71108fda73109bdae48954ad60
+bf867aac3ce44c7c1589a711cf8a81df9b219679d96d1cec3d8bbbeaa2012626
+df8c7802eda201b2d2e0239b409868171fc104ba8b76f10b4da09f6817ffc609
+c413ede267fd1fbab46880c90f80eccf0013185eb48b47ba03df2bdaadef3181
+cb8976f18e13188768170f98c0f844bb78cb04c62ddac59d09fc3fa25dfc1da4
+14deb3df1344f70000000049454e44ae426082
+"""),
+ 'basi3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000133a3ba
+500000000467414d41000186a031e8965f00000300504c5445224400f5ffed77
+ff77cbffff110a003a77002222ffff11ff110000222200ffac5566ff66ff6666
+ff01ff221200dcffffccff994444ff005555220000cbcbff44440055ff55cbcb
+00331a00ffecdcedffffe4ffcbffdcdc44ff446666ff330000442200ededff66
+6600ffa444ffffaaeded0000cbcbfefffffdfffeffff0133ff33552a000101ff
+8888ff00aaaa010100440000888800ffe4cbba5b0022ff22663200ffff99aaaa
+ff550000aaaa00cb630011ff11d4ffaa773a00ff4444dc6b0066000001ff0188
+4200ecffdc6bdc00ffdcba00333300ed00ed7300ffff88994a0011ffff770000
+ff8301ffbabafe7b00fffeff00cb00ff999922ffff880000ffff77008888ffdc
+ff1a33000000aa33ffff009900990000000001326600ffbaff44ffffffaaff00
+770000fefeaa00004a9900ffff66ff22220000998bff1155ffffff0101ff88ff
+005500001111fffffefffdfea4ff4466ffffff66ff003300ffff55ff77770000
+88ff44ff00110077ffff006666ffffed000100fff5ed1111ffffff44ff22ffff
+eded11110088ffff00007793ff2200dcdc3333fffe00febabaff99ffff333300
+63cb00baba00acff55ffffdcffff337bfe00ed00ed5555ffaaffffdcdcff5555
+00000066dcdc00dc00dc83ff017777fffefeffffffcbff5555777700fefe00cb
+00cb0000fe010200010000122200ffff220044449bff33ffd4aa0000559999ff
+999900ba00ba2a5500ffcbcbb4ff66ff9b33ffffbaaa00aa42880053aa00ffaa
+aa0000ed00babaffff1100fe00000044009999990099ffcc99ba000088008800
+dc00ff93220000dcfefffeaa5300770077020100cb0000000033ffedff00ba00
+ff3333edffedffc488bcff7700aa00660066002222dc0000ffcbffdcffdcff8b
+110000cb00010155005500880000002201ffffcbffcbed0000ff88884400445b
+ba00ffbc77ff99ff006600baffba00777773ed00fe00003300330000baff77ff
+004400aaffaafffefe000011220022c4ff8800eded99ff99ff55ff002200ffb4
+661100110a1100ff1111dcffbabaffff88ff88010001ff33ffb98ed362000002
+a249444154789c65d0695c0b001806f03711a9904a94d24dac63292949e5a810
+d244588a14ca5161d1a1323973252242d62157d12ae498c8124d25ca3a11398a
+16e55a3cdffab0ffe7f77d7fcff3528645349b584c3187824d9d19d4ec2e3523
+9eb0ae975cf8de02f2486d502191841b42967a1ad49e5ddc4265f69a899e26b5
+e9e468181baae3a71a41b95669da8df2ea3594c1b31046d7b17bfb86592e4cbe
+d89b23e8db0af6304d756e60a8f4ad378bdc2552ae5948df1d35b52143141533
+33bbbbababebeb3b3bc9c9c9c6c6c0c0d7b7b535323225a5aa8a02024a4bedec
+0a0a2a2bcdcd7d7cf2f3a9a9c9cdcdd8b8adcdd5b5ababa828298982824a4ab2
+b21212acadbdbc1414e2e24859b9a72730302f4f49292c4c57373c9c0a0b7372
+8c8c1c1c3a3a92936d6dfdfd293e3e26262a4a4eaea2424b4b5fbfbc9c323278
+3c0b0ba1303abaae8ecdeeed950d6669a9a7a7a141d4de9e9d5d5cdcd2229b94
+c572716132f97cb1d8db9bc3110864a39795d9db6b6a26267a7a9a98d4d6a6a7
+cb76090ef6f030354d4d75766e686030545464cb393a1a1ac6c68686eae8f8f9
+a9aa4644c8b66d6e1689dcdd2512a994cb35330b0991ad9f9b6b659596a6addd
+d8282fafae5e5323fb8f41d01f76c22fd8061be01bfc041a0323e1002c81cd30
+0b9ec027a0c930014ec035580fc3e112bc069a0b53e11c0c8095f00176c163a0
+e5301baec06a580677600ddc05ba0f13e120bc81a770133ec355a017300d4ec2
+0c7800bbe1219c02fa08f3e13c1c85dbb00a2ec05ea0dff00a6ec15a98027360
+070c047a06d7e1085c84f1b014f6c03fa0b33018b6c0211801ebe018fc00da0a
+6f61113c877eb01d4ec317a085700f26c130f80efbe132bc039a0733e106fc81
+f7f017f6c10aa0d1300a0ec374780943e1382c06fa0a9b60238c83473016cec0
+02f80f73fefe1072afc1e50000000049454e44ae426082
+"""),
+ 'basi6a08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200806000001047d4a
+620000000467414d41000186a031e8965f0000012049444154789cc595414ec3
+3010459fa541b8bbb26641b8069b861e8b4d12c1c112c1452a710a2a65d840d5
+949041fc481ec98ae27c7f3f8d27e3e4648047600fec0d1f390fbbe2633a31e2
+9389e4e4ea7bfdbf3d9a6b800ab89f1bd6b553cfcbb0679e960563d72e0a9293
+b7337b9f988cc67f5f0e186d20e808042f1c97054e1309da40d02d7e27f92e03
+6cbfc64df0fc3117a6210a1b6ad1a00df21c1abcf2a01944c7101b0cb568a001
+909c9cf9e399cf3d8d9d4660a875405d9a60d000b05e2de55e25780b7a5268e0
+622118e2399aab063a815808462f1ab86890fc2e03e48bb109ded7d26ce4bf59
+0db91bac0050747fec5015ce80da0e5700281be533f0ce6d5900b59bcb00ea6d
+200314cf801faab200ea752803a8d7a90c503a039f824a53f4694e7342000000
+0049454e44ae426082
+"""),
+ 'basn0g01': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002001000000005b0147
+590000000467414d41000186a031e8965f0000005b49444154789c2dccb10903
+300c05d1ebd204b24a200b7a346f90153c82c18d0a61450751f1e08a2faaead2
+a4846ccea9255306e753345712e211b221bf4b263d1b427325255e8bdab29e6f
+6aca30692e9d29616ee96f3065f0bf1f1087492fd02f14c90000000049454e44
+ae426082
+"""),
+ 'basn0g02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002002000000001ca13d
+890000000467414d41000186a031e8965f0000001f49444154789c6360085df5
+1f8cf1308850c20053868f0133091f6390b90700bd497f818b0989a900000000
+49454e44ae426082
+"""),
+ # A version of basn0g04 dithered down to 3 bits.
+ 'Basn0g03': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+2900000001734249540371d88211000000fd49444154789c6d90d18906210c84
+c356f22356b2889588604301b112112b11d94a96bb495cf7fe87f32d996f2689
+44741cc658e39c0b118f883e1f63cc89dafbc04c0f619d7d898396c54b875517
+83f3a2e7ac09a2074430e7f497f00f1138a5444f82839c5206b1f51053cca968
+63258821e7f2b5438aac16fbecc052b646e709de45cf18996b29648508728612
+952ca606a73566d44612b876845e9a347084ea4868d2907ff06be4436c4b41a3
+a3e1774285614c5affb40dbd931a526619d9fa18e4c2be420858de1df0e69893
+a0e3e5523461be448561001042b7d4a15309ce2c57aef2ba89d1c13794a109d7
+b5880aa27744fc5c4aecb5e7bcef5fe528ec6293a930690000000049454e44ae
+426082
+"""),
+ 'basn0g04': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+290000000467414d41000186a031e8965f0000004849444154789c6360601014
+545232367671090d4d4b2b2f6720430095dbd1418e002a77e64c720450b9ab56
+912380caddbd9b1c0154ee9933e408a072efde25470095fbee1d1902001f14ee
+01eaff41fa0000000049454e44ae426082
+"""),
+ 'basn0g08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200800000000561125
+280000000467414d41000186a031e8965f0000004149444154789c6364602400
+1408c8b30c05058c0f0829f8f71f3f6079301c1430ca11906764a2795c0c0605
+8c8ff0cafeffcff887e67131181430cae0956564040050e5fe7135e2d8590000
+000049454e44ae426082
+"""),
+ 'basn0g16': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002010000000000681f9
+6b0000000467414d41000186a031e8965f0000005e49444154789cd5d2310ac0
+300c4351395bef7fc6dca093c0287b32d52a04a3d98f3f3880a7b857131363a0
+3a82601d089900dd82f640ca04e816dc06422640b7a03d903201ba05b7819009
+d02d680fa44c603f6f07ec4ff41938cf7f0016d84bd85fae2b9fd70000000049
+454e44ae426082
+"""),
+ 'basn2c08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
+a30000000467414d41000186a031e8965f0000004849444154789cedd5c10900
+300c024085ec91fdb772133b442bf4a1f8cee12bb40d043b800a14f81ca0ede4
+7d4c784081020f4a871fc284071428f0a0743823a94081bb7077a3c00182b1f9
+5e0f40cf4b0000000049454e44ae426082
+"""),
+ 'basn2c16': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000201002000000ac8831
+e00000000467414d41000186a031e8965f000000e549444154789cd596c10a83
+301044a7e0417fcb7eb7fdadf6961e06039286266693cc7a188645e43dd6a08f
+1042003e2fe09aef6472737e183d27335fcee2f35a77b702ebce742870a23397
+f3edf2705dd10160f3b2815fe8ecf2027974a6b0c03f74a6e4192843e75c6c03
+35e8ec3202f5e84c0181bbe8cca967a00d9df3491bb040671f2e6087ce1c2860
+8d1e05f8c7ee0f1d00b667e70df44467ef26d01fbd9bc028f42860f71d188bce
+fb8d3630039dbd59601e7ab3c06cf428507f0634d039afdc80123a7bb1801e7a
+b1802a7a14c89f016d74ce331bf080ce9e08f8414f04bca133bfe642fe5e07bb
+c4ec0000000049454e44ae426082
+"""),
+ 'basn6a08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7a
+f40000000467414d41000186a031e8965f0000006f49444154789cedd6310a80
+300c46e12764684fa1f73f55048f21c4ddc545781d52e85028fc1f4d28d98a01
+305e7b7e9cffba33831d75054703ca06a8f90d58a0074e351e227d805c8254e3
+1bb0420f5cdc2e0079208892ffe2a00136a07b4007943c1004d900195036407f
+011bf00052201a9c160fb84c0000000049454e44ae426082
+"""),
+ 'cs3n3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f0000000373424954030303a392a042
+00000054504c544592ff0000ff9200ffff00ff0000dbff00ff6dffb600006dff
+b6ff00ff9200dbff000049ffff2400ff000024ff0049ff0000ffdb00ff4900ff
+b6ffff0000ff2400b6ffffdb000092ffff6d000024ffff49006dff00df702b17
+0000004b49444154789c85cac70182000000b1b3625754b0edbfa72324ef7486
+184ed0177a437b680bcdd0031c0ed00ea21f74852ed00a1c9ed0086da0057487
+6ed0121cd6d004bda0013a421ff803224033e177f4ae260000000049454e44ae
+426082
+"""),
+ 's09n3p02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000090000000902030000009dffee
+830000000467414d41000186a031e8965f000000037342495404040477f8b5a3
+0000000c504c544500ff000077ffff00ffff7700ff5600640000001f49444154
+789c63600002fbff0c0c56ab19182ca381581a4283f82071200000696505c36a
+437f230000000049454e44ae426082
+"""),
+ 'tbgn3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f00000207504c54457f7f7fafafafab
+abab110000222200737300999999510d00444400959500959595e6e600919191
+8d8d8d620d00898989666600b7b700911600000000730d007373736f6f6faaaa
+006b6b6b676767c41a00cccc0000f30000ef00d51e0055555567670000dd0051
+515100d1004d4d4de61e0038380000b700160d0d00ab00560d00090900009500
+009100008d003333332f2f2f2f2b2f2b2b000077007c7c001a05002b27000073
+002b2b2b006f00bb1600272727780d002323230055004d4d00cc1e00004d00cc
+1a000d00003c09006f6f00002f003811271111110d0d0d55554d090909001100
+4d0900050505000d00e2e200000900000500626200a6a6a6a2a2a29e9e9e8484
+00fb00fbd5d500801100800d00ea00ea555500a6a600e600e6f7f700e200e233
+0500888888d900d9848484c01a007777003c3c05c8c8008080804409007c7c7c
+bb00bbaa00aaa600a61e09056262629e009e9a009af322005e5e5e05050000ee
+005a5a5adddd00a616008d008d00e20016050027270088110078780000c40078
+00787300736f006f44444400aa00c81e004040406600663c3c3c090000550055
+1a1a00343434d91e000084004d004d007c004500453c3c00ea1e00222222113c
+113300331e1e1efb22001a1a1a004400afaf00270027003c001616161e001e0d
+160d2f2f00808000001e00d1d1001100110d000db7b7b7090009050005b3b3b3
+6d34c4230000000174524e530040e6d86600000001624b474402660b7c640000
+01f249444154789c6360c0048c8c58049100575f215ee92e6161ef109cd2a15e
+4b9645ce5d2c8f433aa4c24f3cbd4c98833b2314ab74a186f094b9c2c27571d2
+6a2a58e4253c5cda8559057a392363854db4d9d0641973660b0b0bb76bb16656
+06970997256877a07a95c75a1804b2fbcd128c80b482a0b0300f8a824276a9a8
+ec6e61612b3e57ee06fbf0009619d5fac846ac5c60ed20e754921625a2daadc6
+1967e29e97d2239c8aec7e61fdeca9cecebef54eb36c848517164514af16169e
+866444b2b0b7b55534c815cc2ec22d89cd1353800a8473100a4485852d924a6a
+412adc74e7ad1016ceed043267238c901716f633a812022998a4072267c4af02
+92127005c0f811b62830054935ce017b38bf0948cc5c09955f030a24617d9d46
+63371fd940b0827931cbfdf4956076ac018b592f72d45594a9b1f307f3261b1a
+084bc2ad50018b1900719ba6ba4ca325d0427d3f6161449486f981144cf3100e
+2a5f2a1ce8683e4ddf1b64275240c8438d98af0c729bbe07982b8a1c94201dc2
+b3174c9820bcc06201585ad81b25b64a2146384e3798290c05ad280a18c0a62e
+e898260c07fca80a24c076cc864b777131a00190cdfa3069035eccbc038c30e1
+3e88b46d16b6acc5380d6ac202511c392f4b789aa7b0b08718765990111606c2
+9e854c38e5191878fbe471e749b0112bb18902008dc473b2b2e8e72700000000
+49454e44ae426082
+"""),
+ 'Tp2n3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f00000300504c544502ffff80ff05ff
+7f0703ff7f0180ff04ff00ffff06ff000880ff05ff7f07ffff06ff000804ff00
+0180ff02ffff03ff7f02ffff80ff0503ff7f0180ffff0008ff7f0704ff00ffff
+06ff000802ffffff7f0704ff0003ff7fffff0680ff050180ff04ff000180ffff
+0008ffff0603ff7f80ff05ff7f0702ffffff000880ff05ffff0603ff7f02ffff
+ff7f070180ff04ff00ffff06ff000880ff050180ffff7f0702ffff04ff0003ff
+7fff7f0704ff0003ff7f0180ffffff06ff000880ff0502ffffffff0603ff7fff
+7f0702ffff04ff000180ff80ff05ff0008ff7f07ffff0680ff0504ff00ff0008
+0180ff03ff7f02ffff02ffffffff0604ff0003ff7f0180ffff000880ff05ff7f
+0780ff05ff00080180ff02ffffff7f0703ff7fffff0604ff00ff7f07ff0008ff
+ff0680ff0504ff0002ffff0180ff03ff7fff0008ffff0680ff0504ff000180ff
+02ffff03ff7fff7f070180ff02ffff04ff00ffff06ff0008ff7f0780ff0503ff
+7fffff06ff0008ff7f0780ff0502ffff03ff7f0180ff04ff0002ffffff7f07ff
+ff0604ff0003ff7fff00080180ff80ff05ffff0603ff7f0180ffff000804ff00
+80ff0502ffffff7f0780ff05ffff0604ff000180ffff000802ffffff7f0703ff
+7fff0008ff7f070180ff03ff7f02ffff80ff05ffff0604ff00ff0008ffff0602
+ffff0180ff04ff0003ff7f80ff05ff7f070180ff04ff00ff7f0780ff0502ffff
+ff000803ff7fffff0602ffffff7f07ffff0680ff05ff000804ff0003ff7f0180
+ff02ffff0180ffff7f0703ff7fff000804ff0080ff05ffff0602ffff04ff00ff
+ff0603ff7fff7f070180ff80ff05ff000803ff7f0180ffff7f0702ffffff0008
+04ff00ffff0680ff0503ff7f0180ff04ff0080ff05ffff06ff000802ffffff7f
+0780ff05ff0008ff7f070180ff03ff7f04ff0002ffffffff0604ff00ff7f07ff
+000880ff05ffff060180ff02ffff03ff7f80ff05ffff0602ffff0180ff03ff7f
+04ff00ff7f07ff00080180ffff000880ff0502ffff04ff00ff7f0703ff7fffff
+06ff0008ffff0604ff00ff7f0780ff0502ffff03ff7f0180ffdeb83387000000
+f874524e53000000000000000008080808080808081010101010101010181818
+1818181818202020202020202029292929292929293131313131313131393939
+393939393941414141414141414a4a4a4a4a4a4a4a52525252525252525a5a5a
+5a5a5a5a5a62626262626262626a6a6a6a6a6a6a6a73737373737373737b7b7b
+7b7b7b7b7b83838383838383838b8b8b8b8b8b8b8b94949494949494949c9c9c
+9c9c9c9c9ca4a4a4a4a4a4a4a4acacacacacacacacb4b4b4b4b4b4b4b4bdbdbd
+bdbdbdbdbdc5c5c5c5c5c5c5c5cdcdcdcdcdcdcdcdd5d5d5d5d5d5d5d5dedede
+dededededee6e6e6e6e6e6e6e6eeeeeeeeeeeeeeeef6f6f6f6f6f6f6f6b98ac5
+ca0000012c49444154789c6360e7169150d230b475f7098d4ccc28a96ced9e32
+63c1da2d7b8e9fb97af3d1fb8f3f18e8a0808953544a4dd7c4c2c9233c2621bf
+b4aab17fdacce5ab36ee3a72eafaad87efbefea68702362e7159652d031b07cf
+c0b8a4cce28aa68e89f316aedfb4ffd0b92bf79fbcfcfe931e0a183904e55435
+8decdcbcc22292b3caaadb7b27cc5db67af3be63e72fdf78fce2d31f7a2860e5
+119356d037b374f10e8a4fc92eaa6fee99347fc9caad7b0f9ebd74f7c1db2fbf
+e8a180995f484645dbdccad12f38363dafbcb6a573faeca5ebb6ed3e7ce2c29d
+e76fbefda38702063e0149751d537b67ff80e8d4dcc29a86bea97316add9b0e3
+c0e96bf79ebdfafc971e0a587885e515f58cad5d7d43a2d2720aeadaba26cf5a
+bc62fbcea3272fde7efafac37f3a28000087c0fe101bc2f85f0000000049454e
+44ae426082
+"""),
+ 'tbbn1g04': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+290000000467414d41000186a031e8965f0000000274524e530007e8f7589b00
+000002624b47440000aa8d23320000013e49444154789c55d1cd4b024118c7f1
+efbe6419045b6a48a72d352808b435284f9187ae9b098627a1573a19945beba5
+e8129e8222af11d81e3a4545742de8ef6af6d5762e0fbf0fc33c33f36085cb76
+bc4204778771b867260683ee57e13f0c922df5c719c2b3b6c6c25b2382cea4b9
+9f7d4f244370746ac71f4ca88e0f173a6496749af47de8e44ba8f3bf9bdfa98a
+0faf857a7dd95c7dc8d7c67c782c99727997f41eb2e3c1e554152465bb00fe8e
+b692d190b718d159f4c0a45c4435915a243c58a7a4312a7a57913f05747594c6
+46169866c57101e4d4ce4d511423119c419183a3530cc63db88559ae28e7342a
+1e9c8122b71139b8872d6e913153224bc1f35b60e4445bd4004e20ed6682c759
+1d9873b3da0fbf50137dc5c9bde84fdb2ec8bde1189e0448b63584735993c209
+7a601bd2710caceba6158797285b7f2084a2f82c57c01a0000000049454e44ae
+426082
+"""),
+ 'tbrn2c08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
+a30000000467414d41000186a031e8965f0000000674524e53007f007f007f8a
+33334f00000006624b474400ff0000000033277cf3000004d649444154789cad
+965f68537714c73fd912d640235e692f34d0406fa0c1663481045ab060065514
+56660a295831607df0a1488715167060840a1614e6431e9cb34fd2c00a762c85
+f6a10f816650c13b0cf40612e1822ddc4863bd628a8924d23d6464f9d3665dd9
+f7e977ce3dbff3cd3939bfdfef6bb87dfb364782dbed065ebe7cd93acc78b4ec
+a228debd7bb7bfbfbfbbbbfb7f261045311a8d261209405194274f9ea4d3e916
+f15f1c3eb5dd6e4fa5fecce526239184a2b0b8486f6f617171b1f5ae4311381c
+8e57af5e5dbd7a351088150a78bd389d44222c2f93cdfe66b7db8f4ee07038b6
+b6b6bebf766d7e7e7e60a06432313b4ba984c3c1c4049a46b95c5a58583822c1
+dbb76f27272733d1b9df853c3030c0f232562b9108cf9eb1b888d7cbf030abab
+31abd5fa1f08dc6ef7e7cf9f1f3f7e1c8944745d4f1400c62c001313acad21cb
+b8dd2c2c603271eb1640341aad4c6d331aa7e8c48913a150a861307ecc11e964
+74899919bc5e14e56fffc404f1388502f178dceff7ef4bf0a5cfe7abb533998c
+e5f9ea2f1dd88c180d64cb94412df3dd57e83a6b3b3c7a84c98420100c72fd3a
+636348bae726379fe69e8e8d8dbd79f3a6558b0607079796965256479b918085
+7b02db12712b6181950233023f3f647494ee6e2e5ea45864cce5b8a7fe3acffc
+3aebb22c2bd5d20e22d0757d7b7bbbbdbd3d94a313bed1b0aa3cd069838b163a
+8d4c59585f677292d0b84d9a995bd337def3fe6bbe5e6001989b9b6bfe27ea08
+36373781542ab56573248b4c5bc843ac4048c7ab21aa24ca00534c25482828a3
+8c9ee67475bbaaaab22cb722c8e57240a150301a8d219de94e44534d7d90e885
+87acb0e2c4f9800731629b6c5ee14a35a6b9887d2a0032994cb9cf15dbe59650
+ff7b46a04c9a749e7cc5112214266cc65c31354d5b5d5d3d90209bcd5616a552
+a95c2e87f2a659bd9ee01c2cd73964e438f129a6aa9e582c363838b80f81d7eb
+5555b56a2a8ad2d9d7affd0409f8015c208013fea00177b873831b0282c964f2
+783c1e8fa7582cee5f81a669b5e6eeeeaee58e8559b0c233d8843c7c0b963a82
+34e94b5cb2396d7d7d7db22c8ba258fb0afd43f0e2c58b919191ba9de9b4d425
+118329b0c3323c8709d02041b52b4ea7f39de75d2a934a2693c0a953a76a93d4
+5d157ebf7f6565a5542a553df97c5e10045dd731c130b86113cc300cbd489224
+08422a952a140a95788fc763b1d41558d7a2d7af5f5fb870a1d6a3aaaacd6603
+18802da84c59015bd2e6897b745d9765b99a1df0f97c0daf74e36deaf7fbcd66
+73ad2797cb89a2c839880188a2e8743a8bc5a22ccbba5e376466b3b9bdbdbd21
+6123413a9d0e0402b51e4dd3bababa788eb022b85caeb6b6364551b6b7b76942
+43f7f727007a7a7a04a1ee8065b3595fde2768423299ac1ec6669c3973e65004
+c0f8f878ad69341a33994ced2969c0d0d0502412f9f8f163f3a7fd654b474787
+288ad53e74757535df6215b85cae60302849d2410aecc037f9f2e5cbd5b5c160
+680eb0dbede170381c0e7ff8f0a185be3b906068684892a4ca7a6f6faff69328
+8ad3d3d3f7efdfdfdbdbfb57e96868a14d0d0643381c96242997cbe5f3794010
+84603078fcf8f1d6496bd14a3aba5c2ea7d369341a5555b5582c8140e0fcf9f3
+1b1b1b87cf4eeb0a8063c78e45a3d19e9e1ebfdfdf5a831e844655d18093274f
+9e3d7bf6d3a74f3b3b3b47c80efc05ff7af28fefb70d9b0000000049454e44ae
+426082
+"""),
+ 'basn6a16': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020100600000023eaa6
+b70000000467414d41000186a031e8965f00000d2249444154789cdd995f6c1c
+d775c67ff38fb34b724d2ee55a8e4b04a0ac87049100cab4dbd8c6528902cb4d
+10881620592e52d4325ac0905bc98a94025e71fd622cb5065ac98a0c283050c0
+728a00b6e542a1d126885cd3298928891d9a0444037e904434951d4b90b84b2f
+c9dde1fcebc33977a95555348f411e16dfce9d3b77ee77eebde77ce78c95a669
+0ad07c17009a13edd898b87dfb1fcb7d2b4d1bff217f33df80deb1e6267df0ff
+c1e6e6dfafdf1f5a7fd30f9aef66b6d546dd355bf02c40662e3307f9725a96c6
+744c3031f83782f171c148dbc3bf1774f5dad1e79d6f095a3f54d4fbec5234ef
+d9a2f8d73afe4f14f57ef4f42def7b44f19060f06b45bddf1c5534d77fd922be
+2973a15a82e648661c6e3240aa3612ead952b604bde57458894f29deaf133bac
+13d2766f5227a4a3b8cf08da7adfd6fbd6bd8a4fe9dbb43d35e3dfa3f844fbf8
+9119bf4f7144094fb56333abf8a86063ca106f94b3a3b512343765e60082097f
+1bb86ba72439a653519b09f5cee1ce61c897d37eedf5553580ae60f4af8af33a
+b14fd400b6a0f34535c0434afc0b3a9f07147527a5fa7ca218ff56c74d74dc3f
+155cfd3325fc278acf2ae1cb4a539f5f9937c457263b0bd51234c732a300cdd1
+cc1840f0aaff54db0e4874ed5a9b5d6d27d4bb36746d80de72baa877ff4b275a
+d7895ed1897ea4139b5143fcbb1a62560da1ed9662aaed895ec78a91c18795b8
+5e07ab4af8ba128e95e682e0728bf8f2e5ae815a091a53d902ac1920d8e05f06
+589de8d8d66680789f4e454fb9d9ec66cd857af796ee2d902fa73fd5bba775a2
+153580ae44705ed0d37647d15697cb8f14bfa3e3e8fdf8031d47af571503357c
+f30d25acedcbbf135c9a35c49766ba07ab255859e8ec03684e66860182dff8f7
+0304bff6ff1c20fc81b7afdd00a71475539a536e36bb5973a19e3b923b02bde5
+e4efd4003ac170eb2d13fe274157afedbd82d6fb3a9a1e85e4551d47cf7078f8
+9671fe4289ebf5f2bf08d63f37c4eb4773c55a0996efeefa0ca011671d8060ca
+2f0004c7fcc300e166ef0240f825efe3361f106d57d423d0723f7acacd66376b
+2ed47b7a7a7a205f4ef4ac4691e0aad9aa0d41cf13741c3580a506487574ddca
+61a8c403c1863ebfbcac3475168b2de28b8b3d77544bb05ce92a02aceced3c0d
+d0cc65ea371b201cf1c601c24dde1c4078cedbdeb60322f50126a019bf6edc9b
+39e566b39b3517eaf97c3e0fbde5e4491d45bd74537145d155b476aa0176e868
+c6abebf30dbd5e525c54ac8e18e2d56abeb756827a3d970358a97416019a6f64
+f60004fdfe1580d5c98e618070cc1b05887eee7e0d209a70db7d8063029889b4
+c620ead78d7b33a7dc6c76b3e6427ddddbebde867c393aa7845e5403e8ca794a
+d0d6fb897af5f03525fe5782f5e7046bdaef468bf88d1debc6ab25583cd17310
+6079b9ab0ba059c914018245bf076075b5a303200c3c1f209a733701444fbbaf
+00c4134ebb016c5d0b23614c243701cdf875e3decce9349bddacb9505fbf7dfd
+76e82d87736a00f5d2b5ffd4b7dce2719a4d25ae717ee153c1abef18e257cfad
+7fa45682da48ef38c052b53b0fd06864b300c151ff08c0ea431de701a287dd5f
+004497dc7b01a253ee3e80b8c7f91c20f967fb6fdb7c80ada7d8683723614c24
+3701cdf875e3decc29379bddacb950ef3fd47f08f2e5a61ea4aa2a3eb757cd55
+13345efcfa59c12b2f19e2578ef77fb75a82854ffbee01a83f977b11a031931d
+040802df07082b5e11207cc17b1e209a770700e2df0a83e409fb7580f827c230
+99b06fd901fb058d6835dacd481813c94d40337eddb83773cacd66376b2ed437
+bebcf165e82d2f4e4beb7f3fa6e652c2d7ee10bc78c010bfb87fe3c95a09ae9f
+bd732740bd2fb700d0f865f64180e059ff044018ca0ca28a5b04883f701e0088
+bfec7c0c909cb71f0448c6ec518074b375012079d9dedf66004bcfbc51eb2dd1
+aadacd481813c94d40337eddb83773cacd66376b2ed487868686205fbe7c49ef
+5605a73f34c4a7a787eeab96e0da81bb4e022c15ba27019a5b339300e16bf286
+a8eae601e25866907cdf3e0890acb36f00245fb57f05904e59c300e92561946e
+b2e600d209ab7d07f04d458dfb46ad1bd16ab49b913026929b8066fcba716fe6
+949bcd6ed65ca8ef7e7cf7e3d05b7e7c8f217ee6cdddbb6a25a856f37980e0c7
+fe4e80a82623c48193014846ec7180f4acf518409aca0cd28a5504e03b32c374
+de1a00608a0240faaa327a4b19fe946fb6f90054dbb5f2333d022db56eb4966a
+3723614c243701cdf8f556bea8a7dc6c76b3e66bd46584ddbbcebc0990cf4b0f
+ff4070520c282338a7e26700ec725202b01e4bcf0258963c6f1d4d8f0030cb20
+805549c520930c03584fa522b676f11600ffc03fde3e1b3489a9c9054c9aa23b
+c08856a3dd8c843191dc0434e3d78d7b33a75c36fb993761f7ae5a69f72ef97f
+e6ad336fed7e1c60e8bee96980bbdebbb60da07b7069062033d9dc0ae03d296f
+70ab511ec071640676252902d833c916007b3e1900b0a6d2028035968e025861
+ea01581369fb11488c34d18cbc95989afccca42baad65ba2d5683723614c24d7
+8066fcbab8b7e96918baaf5aaa56219f975fb50a43f7c9bde90fa73f1c1a02d8
+78f2e27e803b77ca08b90519315b6fe400fc1392097a9eccc0ad444500e70199
+a1331f0f00d8934901c07e5d526ceb87c2d07e2579badd005a2b31a5089391b7
+1253358049535a6add8856dd0146c298482e01ede27ed878b256ba7600ee3a09
+c18fc1df09fe01084ec25defc1b56db0f1a4f4bd78e0e2818d2f0334e7330300
+7df7c888b917e50dd9c1c60c80efcb0cbc63e1f700bce7c31700dccbd1060027
+8add9b0de06c8e2f00d84962b7d7030e2a61538331b98051f92631bd253f336a
+dd8856a3dd44c25c390efddfad96ae9f853b77c25201ba27c533b8bdf28b6ad0
+3d084b33d2e7fa59099e9901b8f2d29597fa0f01848f78e70082117f1ca07b76
+6910209b9519f895a008d031bbba05c09d8f06005c5b18b8fba25300cea6780e
+c03e911c6ccf06d507b48a4fa606634a114609de929f9934c5a87511ad57cfc1
+fa476aa5854fa1ef1e3910b905686e85cc24c40138198915f133d2d6dc2a7dea
+7df2ccc2a752faf2cec1d577aebeb37e3b4034eeee0008dff3be0e6b923773b4
+7904c0ef9119767cb4fa1500ef1361e08e452500f71561e84cc4ed3e20fab6a2
+c905f40cb76a3026bf3319b91ac2e46792a6dcd801ebc6aba5da08f48ecb81c8
+bd088d5f42f6417191de93908c803d0e76199292b485af41b60e8d9c3c537f0e
+8211f0c7211a077707dc18b931b2ee6d80a4d7ae024491ebc24d4a708ff70680
+7f25e807e8785f1878e322d6ddaf453f0770ff2dfa769b01423dbbad72a391b6
+5a7c3235985629423372494cab55c8f7d64a8b27a0e7202c55a13b0f8d19c80e
+4ae9ca3f015115dc3ca467c17a4c7ee95970ab10e5a54ff0ac3cd39881ee5958
+1a84f03df0be0e492fd855a8d6aa35d10b4962dbb0a604a3d3ee5e80a8eee600
+a24977f8660378bf0bbf00e01d0a8fb7f980f04b8aa6ce6aca8d5a7533c52753
+839152c4e222f4dc512dd5eb90cbc981e8ea12cf90cd8a8bf47d89159e2741d3
+7124f65b96fcd254dae258fa84a13c13043246a32129574787e49eae2b49b86d
+c3e2e78b9ff7f4002415bb08907c66df0d103b4e0c104db90500ff70700c203a
+ee1e82dba4c3e16e256c0acca6ceaae9afd1f612d7eb472157ac95962bd05594
+7dd1598466053245088e827f44628657942a825b84e4fb601f84b4025611aca3
+901e01bb024911dc0a4445f08e41f83df02b10142173149ab71baf027611ea95
+7a257704201d14cd9af4d90b00f194530088cb4e09c0df1c5c0088f7393f6833
+c0aa3ac156655de3bca9b34ab9716906ba07aba5e5bba1eb3358d90b9da7c533
+64f6888bf47b60f521e8380fe10be03d2feac17900927560df40f4e48f805960
+50328d648bf4893f9067c217a0631656b7c898c122847bc07b03a2d3e0ee85e4
+33b0ef867450c4fad2ecd26cf7168074c0ba0c904cdac300c9cfec4701924df6
+1cdca61e10685c6f7d52d0caba1498972f43d740adb4b2009d7d7220b20e3473
+90a943d00ffe959bb6eac3e0fe42ea49ee00c45f06e76329b1dabf127d690d80
+5581b408f63c2403e0cc433c00ee658836803b0fd100747c04ab5f917704fd10
+d5c1cd41ec801343d207f602a403605d86e5f9e5f9ae0d00e994556833806685
+c931fb709b0f08b4e869bea5c827859549e82c544b8d29c816a0390999613920
+7e610d5727a16318c2003c1fa24be0de2b32caf92224e7c17e5004b6350c4c01
+05601218066b0ad28224e149019c086257ca315102de2712903bde97b8144d82
+3b2c6ac52d403c054e019249b087f53d0558995a99ea946c70cc927458b3c1ff
+550f30050df988d4284376b4566a8e416654cc921985e037e0df0fc131f00f4b
+acf0c6211c036f14a239703741740adc7da227edd7e56b833d0ae92549b4d357
+25dfb49ed2ff63908e6adf27d6d0dda7638d4154d2778daca17f58e61297c129
+41f233b01f5dc3740cac51688c35c6b22580f48224fee9b83502569a66b629f1
+09f3713473413e2666e7fe6f6c6efefdfafda1f56f6e06f93496d9d67cb7366a
+9964b6f92e64b689196ec6c604646fd3fe4771ff1bf03f65d8ecc3addbb5f300
+00000049454e44ae426082
+"""),
+}
+
+def test_suite(options, args):
+ """
+ Create a PNG test image and write the file to stdout.
+ """
+
+ import re
+
+ # Below is a big stack of test image generators.
+ # They're all really tiny, so PEP 8 rules are suspended.
+
+ def test_gradient_horizontal_lr(x, y): return x
+ def test_gradient_horizontal_rl(x, y): return 1-x
+ def test_gradient_vertical_tb(x, y): return y
+ def test_gradient_vertical_bt(x, y): return 1-y
+ def test_radial_tl(x, y): return max(1-math.sqrt(x*x+y*y), 0.0)
+ def test_radial_center(x, y): return test_radial_tl(x-0.5, y-0.5)
+ def test_radial_tr(x, y): return test_radial_tl(1-x, y)
+ def test_radial_bl(x, y): return test_radial_tl(x, 1-y)
+ def test_radial_br(x, y): return test_radial_tl(1-x, 1-y)
+ def test_stripe(x, n): return float(int(x*n) & 1)
+ def test_stripe_h_2(x, y): return test_stripe(x, 2)
+ def test_stripe_h_4(x, y): return test_stripe(x, 4)
+ def test_stripe_h_10(x, y): return test_stripe(x, 10)
+ def test_stripe_v_2(x, y): return test_stripe(y, 2)
+ def test_stripe_v_4(x, y): return test_stripe(y, 4)
+ def test_stripe_v_10(x, y): return test_stripe(y, 10)
+ def test_stripe_lr_10(x, y): return test_stripe(x+y, 10)
+ def test_stripe_rl_10(x, y): return test_stripe(1+x-y, 10)
+ def test_checker(x, y, n): return float((int(x*n) & 1) ^ (int(y*n) & 1))
+ def test_checker_8(x, y): return test_checker(x, y, 8)
+ def test_checker_15(x, y): return test_checker(x, y, 15)
+ def test_zero(x, y): return 0
+ def test_one(x, y): return 1
+
+ test_patterns = {
+ 'GLR': test_gradient_horizontal_lr,
+ 'GRL': test_gradient_horizontal_rl,
+ 'GTB': test_gradient_vertical_tb,
+ 'GBT': test_gradient_vertical_bt,
+ 'RTL': test_radial_tl,
+ 'RTR': test_radial_tr,
+ 'RBL': test_radial_bl,
+ 'RBR': test_radial_br,
+ 'RCTR': test_radial_center,
+ 'HS2': test_stripe_h_2,
+ 'HS4': test_stripe_h_4,
+ 'HS10': test_stripe_h_10,
+ 'VS2': test_stripe_v_2,
+ 'VS4': test_stripe_v_4,
+ 'VS10': test_stripe_v_10,
+ 'LRS': test_stripe_lr_10,
+ 'RLS': test_stripe_rl_10,
+ 'CK8': test_checker_8,
+ 'CK15': test_checker_15,
+ 'ZERO': test_zero,
+ 'ONE': test_one,
+ }
+
+ def test_pattern(width, height, bitdepth, pattern):
+ """Create a single plane (monochrome) test pattern. Returns a
+ flat row flat pixel array.
+ """
+
+ maxval = 2**bitdepth-1
+ if maxval > 255:
+ a = array('H')
+ else:
+ a = array('B')
+ fw = float(width)
+ fh = float(height)
+ pfun = test_patterns[pattern]
+ for y in range(height):
+ fy = float(y)/fh
+ for x in range(width):
+ a.append(int(round(pfun(float(x)/fw, fy) * maxval)))
+ return a
+
+ def test_rgba(size=(256,256), bitdepth=8,
+ red="GTB", green="GLR", blue="RTL", alpha=None):
+ """
+ Create a test image. Each channel is generated from the
+ specified pattern; any channel apart from red can be set to
+ None, which will cause it not to be in the image. It
+ is possible to create all PNG channel types (L, RGB, LA, RGBA),
+ as well as non PNG channel types (RGA, and so on).
+ *size* is a pair: (*width*,*height).
+ """
+
+ i = test_pattern(size[0], size[1], bitdepth, red)
+ psize = 1
+ for channel in (green, blue, alpha):
+ if channel:
+ c = test_pattern(size[0], size[1], bitdepth, channel)
+ i = interleave_planes(i, c, psize, 1)
+ psize += 1
+ return i
+
+ def pngsuite_image(name):
+ """
+ Create a test image by reading an internal copy of the files
+ from the PngSuite. Returned in flat row flat pixel format.
+ """
+
+ if name not in _pngsuite:
+ raise NotImplementedError("cannot find PngSuite file %s (use -L for a list)" % name)
+ r = Reader(bytes=_pngsuite[name])
+ w,h,pixels,meta = r.asDirect()
+ # LAn for n < 8 is a special case for which we need to rescale
+ # the data.
+ if meta['greyscale'] and meta['alpha'] and meta['bitdepth'] < 8:
+ factor = 255 // (2**meta['bitdepth']-1)
+ def rescale(data):
+ for row in data:
+ yield map(factor.__mul__, row)
+ pixels = rescale(pixels)
+ meta['bitdepth'] = 8
+ arraycode = 'BH'[meta['bitdepth']>8]
+ return w, h, array(arraycode, itertools.chain(*pixels)), meta
+
+ # The body of test_suite()
+
+ size = (256,256)
+ # Expect option of the form '64,40'.
+ if options.test_size:
+ size = re.findall(r'\d+', options.test_size)
+ if len(size) not in [1,2]:
+ raise ValueError(
+ 'size should be one or two numbers, separated by punctuation')
+ if len(size) == 1:
+ size *= 2
+ assert len(size) == 2
+ size = map(int, size)
+ options.bitdepth = options.test_depth
+ options.greyscale=bool(options.test_black)
+
+ kwargs = {}
+ if options.test_red:
+ kwargs["red"] = options.test_red
+ if options.test_green:
+ kwargs["green"] = options.test_green
+ if options.test_blue:
+ kwargs["blue"] = options.test_blue
+ if options.test_alpha:
+ kwargs["alpha"] = options.test_alpha
+ if options.greyscale:
+ if options.test_red or options.test_green or options.test_blue:
+ raise ValueError("cannot specify colours (R, G, B) when greyscale image (black channel, K) is specified")
+ kwargs["red"] = options.test_black
+ kwargs["green"] = None
+ kwargs["blue"] = None
+ options.alpha = bool(options.test_alpha)
+ if not args:
+ pixels = test_rgba(size, options.bitdepth, **kwargs)
+ else:
+ w,h,pixels,meta = pngsuite_image(args[0])
+ size = (w,h)
+ for k in ['bitdepth', 'alpha', 'greyscale']:
+ setattr(options, k, meta[k])
+
+ writer = Writer(size[0], size[1],
+ bitdepth=options.bitdepth,
+ transparent=options.transparent,
+ background=options.background,
+ gamma=options.gamma,
+ greyscale=options.greyscale,
+ alpha=options.alpha,
+ compression=options.compression,
+ interlace=options.interlace)
+ writer.write_array(sys.stdout, pixels)
+
+def read_pam_header(infile):
+ """
+ Read (the rest of a) PAM header. `infile` should be positioned
+ immediately after the initial 'P7' line (at the beginning of the
+ second line). Returns are as for `read_pnm_header`.
+ """
+
+ # Unlike PBM, PGM, and PPM, we can read the header a line at a time.
+ header = dict()
+ while True:
+ l = infile.readline().strip()
+ if l == strtobytes('ENDHDR'):
+ break
+ if not l:
+ raise EOFError('PAM ended prematurely')
+ if l[0] == strtobytes('#'):
+ continue
+ l = l.split(None, 1)
+ if l[0] not in header:
+ header[l[0]] = l[1]
+ else:
+ header[l[0]] += strtobytes(' ') + l[1]
+
+ required = ['WIDTH', 'HEIGHT', 'DEPTH', 'MAXVAL']
+ required = [strtobytes(x) for x in required]
+ WIDTH,HEIGHT,DEPTH,MAXVAL = required
+ present = [x for x in required if x in header]
+ if len(present) != len(required):
+ raise Error('PAM file must specify WIDTH, HEIGHT, DEPTH, and MAXVAL')
+ width = int(header[WIDTH])
+ height = int(header[HEIGHT])
+ depth = int(header[DEPTH])
+ maxval = int(header[MAXVAL])
+ if (width <= 0 or
+ height <= 0 or
+ depth <= 0 or
+ maxval <= 0):
+ raise Error(
+ 'WIDTH, HEIGHT, DEPTH, MAXVAL must all be positive integers')
+ return 'P7', width, height, depth, maxval
+
+def read_pnm_header(infile, supported=('P5','P6')):
+ """
+ Read a PNM header, returning (format,width,height,depth,maxval).
+ `width` and `height` are in pixels. `depth` is the number of
+ channels in the image; for PBM and PGM it is synthesized as 1, for
+ PPM as 3; for PAM images it is read from the header. `maxval` is
+ synthesized (as 1) for PBM images.
+ """
+
+ # Generally, see http://netpbm.sourceforge.net/doc/ppm.html
+ # and http://netpbm.sourceforge.net/doc/pam.html
+
+ supported = [strtobytes(x) for x in supported]
+
+ # Technically 'P7' must be followed by a newline, so by using
+ # rstrip() we are being liberal in what we accept. I think this
+ # is acceptable.
+ type = infile.read(3).rstrip()
+ if type not in supported:
+ raise NotImplementedError('file format %s not supported' % type)
+ if type == strtobytes('P7'):
+ # PAM header parsing is completely different.
+ return read_pam_header(infile)
+ # Expected number of tokens in header (3 for P4, 4 for P6)
+ expected = 4
+ pbm = ('P1', 'P4')
+ if type in pbm:
+ expected = 3
+ header = [type]
+
+ # We have to read the rest of the header byte by byte because the
+ # final whitespace character (immediately following the MAXVAL in
+ # the case of P6) may not be a newline. Of course all PNM files in
+ # the wild use a newline at this point, so it's tempting to use
+ # readline; but it would be wrong.
+ def getc():
+ c = infile.read(1)
+ if not c:
+ raise Error('premature EOF reading PNM header')
+ return c
+
+ c = getc()
+ while True:
+ # Skip whitespace that precedes a token.
+ while c.isspace():
+ c = getc()
+ # Skip comments.
+ while c == '#':
+ while c not in '\n\r':
+ c = getc()
+ if not c.isdigit():
+ raise Error('unexpected character %s found in header' % c)
+ # According to the specification it is legal to have comments
+ # that appear in the middle of a token.
+ # This is bonkers; I've never seen it; and it's a bit awkward to
+ # code good lexers in Python (no goto). So we break on such
+ # cases.
+ token = strtobytes('')
+ while c.isdigit():
+ token += c
+ c = getc()
+ # Slight hack. All "tokens" are decimal integers, so convert
+ # them here.
+ header.append(int(token))
+ if len(header) == expected:
+ break
+ # Skip comments (again)
+ while c == '#':
+ while c not in '\n\r':
+ c = getc()
+ if not c.isspace():
+ raise Error('expected header to end with whitespace, not %s' % c)
+
+ if type in pbm:
+ # synthesize a MAXVAL
+ header.append(1)
+ depth = (1,3)[type == strtobytes('P6')]
+ return header[0], header[1], header[2], depth, header[3]
+
+def write_pnm(file, width, height, pixels, meta):
+ """Write a Netpbm PNM/PAM file."""
+
+ bitdepth = meta['bitdepth']
+ maxval = 2**bitdepth - 1
+ # Rudely, the number of image planes can be used to determine
+ # whether we are L (PGM), LA (PAM), RGB (PPM), or RGBA (PAM).
+ planes = meta['planes']
+ # Can be an assert as long as we assume that pixels and meta came
+ # from a PNG file.
+ assert planes in (1,2,3,4)
+ if planes in (1,3):
+ if 1 == planes:
+ # PGM
+ # Could generate PBM if maxval is 1, but we don't (for one
+ # thing, we'd have to convert the data, not just blat it
+ # out).
+ fmt = 'P5'
+ else:
+ # PPM
+ fmt = 'P6'
+ file.write('%s %d %d %d\n' % (fmt, width, height, maxval))
+ if planes in (2,4):
+ # PAM
+ # See http://netpbm.sourceforge.net/doc/pam.html
+ if 2 == planes:
+ tupltype = 'GRAYSCALE_ALPHA'
+ else:
+ tupltype = 'RGB_ALPHA'
+ file.write('P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n'
+ 'TUPLTYPE %s\nENDHDR\n' %
+ (width, height, planes, maxval, tupltype))
+ # Values per row
+ vpr = planes * width
+ # struct format
+ fmt = '>%d' % vpr
+ if maxval > 0xff:
+ fmt = fmt + 'H'
+ else:
+ fmt = fmt + 'B'
+ for row in pixels:
+ file.write(struct.pack(fmt, *row))
+ file.flush()
+
+def color_triple(color):
+ """
+ Convert a command line colour value to a RGB triple of integers.
+ FIXME: Somewhere we need support for greyscale backgrounds etc.
+ """
+ if color.startswith('#') and len(color) == 4:
+ return (int(color[1], 16),
+ int(color[2], 16),
+ int(color[3], 16))
+ if color.startswith('#') and len(color) == 7:
+ return (int(color[1:3], 16),
+ int(color[3:5], 16),
+ int(color[5:7], 16))
+ elif color.startswith('#') and len(color) == 13:
+ return (int(color[1:5], 16),
+ int(color[5:9], 16),
+ int(color[9:13], 16))
+
+
+def _main(argv):
+ """
+ Run the PNG encoder with options from the command line.
+ """
+
+ # Parse command line arguments
+ from optparse import OptionParser
+ import re
+ version = '%prog ' + re.sub(r'( ?\$|URL: |Rev:)', '', __version__)
+ parser = OptionParser(version=version)
+ parser.set_usage("%prog [options] [imagefile]")
+ parser.add_option('-r', '--read-png', default=False,
+ action='store_true',
+ help='Read PNG, write PNM')
+ parser.add_option("-i", "--interlace",
+ default=False, action="store_true",
+ help="create an interlaced PNG file (Adam7)")
+ parser.add_option("-t", "--transparent",
+ action="store", type="string", metavar="color",
+ help="mark the specified colour (#RRGGBB) as transparent")
+ parser.add_option("-b", "--background",
+ action="store", type="string", metavar="color",
+ help="save the specified background colour")
+ parser.add_option("-a", "--alpha",
+ action="store", type="string", metavar="pgmfile",
+ help="alpha channel transparency (RGBA)")
+ parser.add_option("-g", "--gamma",
+ action="store", type="float", metavar="value",
+ help="save the specified gamma value")
+ parser.add_option("-c", "--compression",
+ action="store", type="int", metavar="level",
+ help="zlib compression level (0-9)")
+ parser.add_option("-T", "--test",
+ default=False, action="store_true",
+ help="create a test image (a named PngSuite image if an argument is supplied)")
+ parser.add_option('-L', '--list',
+ default=False, action='store_true',
+ help="print list of named test images")
+ parser.add_option("-R", "--test-red",
+ action="store", type="string", metavar="pattern",
+ help="test pattern for the red image layer")
+ parser.add_option("-G", "--test-green",
+ action="store", type="string", metavar="pattern",
+ help="test pattern for the green image layer")
+ parser.add_option("-B", "--test-blue",
+ action="store", type="string", metavar="pattern",
+ help="test pattern for the blue image layer")
+ parser.add_option("-A", "--test-alpha",
+ action="store", type="string", metavar="pattern",
+ help="test pattern for the alpha image layer")
+ parser.add_option("-K", "--test-black",
+ action="store", type="string", metavar="pattern",
+ help="test pattern for greyscale image")
+ parser.add_option("-d", "--test-depth",
+ default=8, action="store", type="int",
+ metavar='NBITS',
+ help="create test PNGs that are NBITS bits per channel")
+ parser.add_option("-S", "--test-size",
+ action="store", type="string", metavar="w[,h]",
+ help="width and height of the test image")
+ (options, args) = parser.parse_args(args=argv[1:])
+
+ # Convert options
+ if options.transparent is not None:
+ options.transparent = color_triple(options.transparent)
+ if options.background is not None:
+ options.background = color_triple(options.background)
+
+ if options.list:
+ names = list(_pngsuite)
+ names.sort()
+ for name in names:
+ print name
+ return
+
+ # Run regression tests
+ if options.test:
+ return test_suite(options, args)
+
+ # Prepare input and output files
+ if len(args) == 0:
+ infilename = '-'
+ infile = sys.stdin
+ elif len(args) == 1:
+ infilename = args[0]
+ infile = open(infilename, 'rb')
+ else:
+ parser.error("more than one input file")
+ outfile = sys.stdout
+ if sys.platform == "win32":
+ import msvcrt, os
+ msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
+
+ if options.read_png:
+ # Encode PNG to PPM
+ png = Reader(file=infile)
+ width,height,pixels,meta = png.asDirect()
+ write_pnm(outfile, width, height, pixels, meta)
+ else:
+ # Encode PNM to PNG
+ format, width, height, depth, maxval = \
+ read_pnm_header(infile, ('P5','P6','P7'))
+ # When it comes to the variety of input formats, we do something
+ # rather rude. Observe that L, LA, RGB, RGBA are the 4 colour
+ # types supported by PNG and that they correspond to 1, 2, 3, 4
+ # channels respectively. So we use the number of channels in
+ # the source image to determine which one we have. We do not
+ # care about TUPLTYPE.
+ greyscale = depth <= 2
+ pamalpha = depth in (2,4)
+ supported = map(lambda x: 2**x-1, range(1,17))
+ try:
+ mi = supported.index(maxval)
+ except ValueError:
+ raise NotImplementedError(
+ 'your maxval (%s) not in supported list %s' %
+ (maxval, str(supported)))
+ bitdepth = mi+1
+ writer = Writer(width, height,
+ greyscale=greyscale,
+ bitdepth=bitdepth,
+ interlace=options.interlace,
+ transparent=options.transparent,
+ background=options.background,
+ alpha=bool(pamalpha or options.alpha),
+ gamma=options.gamma,
+ compression=options.compression)
+ if options.alpha:
+ pgmfile = open(options.alpha, 'rb')
+ format, awidth, aheight, adepth, amaxval = \
+ read_pnm_header(pgmfile, 'P5')
+ if amaxval != '255':
+ raise NotImplementedError(
+ 'maxval %s not supported for alpha channel' % amaxval)
+ if (awidth, aheight) != (width, height):
+ raise ValueError("alpha channel image size mismatch"
+ " (%s has %sx%s but %s has %sx%s)"
+ % (infilename, width, height,
+ options.alpha, awidth, aheight))
+ writer.convert_ppm_and_pgm(infile, pgmfile, outfile)
+ else:
+ writer.convert_pnm(infile, outfile)
+
+
+if __name__ == '__main__':
+ try:
+ _main(sys.argv)
+ except Error, e:
+ print >>sys.stderr, e
=== added file 'slidewall_engine/wallbase.py'
--- slidewall_engine/wallbase.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/wallbase.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,91 @@
+import urllib
+import re
+class WallBase:
+ def __init__(self):
+ self.wallbase_url = 'http://wallbase.cc/search/'
+
+ self.wallbase_newest_url = 'http://wallbase.cc/search/'
+
+ self.wallbase_random_url = 'http://wallbase.cc/random/'
+
+ self.wallbase_search_url = '/0/213/eqeq/0x0/0/1/1/0/60/relevance/desc/wallpapers'
+ self.new_returnlist = {}
+ self.ran_returnlist = {}
+ self.sea_returnlist = {}
+
+ def get_searched_url(self,tag):
+ self.final_url = self.wallbase_url + tag + self.wallbase_search_url
+ if(len(self.sea_returnlist) <= 0 ):
+ self.final_url = self.wallbase_newest_url
+ f = urllib.urlopen(self.final_url)
+ s = f.read()
+ counter = -1;
+ for line in s.split('\n'):
+ if('http://wallbase.cc/wallpaper/' in line):
+ value = line[line.find("http://wallbase.cc/wallpaper/"):line.find('" id="')]
+ #print value
+ ff = urllib.urlopen(value)
+ ss = ff.read()
+ for lline in ss.split('\n'):
+ if('<img src="http://' in lline) and ('.jpg' in lline) and (' alt=' in lline):
+ vvalue = lline[lline.find('<img src="http://')+10 :lline.find('" alt="')]
+ #print "::::::::::::::::::" + vvalue
+ counter = counter + 1
+ self.sea_returnlist[str(counter)]= vvalue
+ #print self.sea_returnlist
+ return self.sea_returnlist
+ else:
+ return self.sea_returnlist
+
+ def get_newest_url(self):
+ if(len(self.new_returnlist) <= 0 ):
+ self.final_url = self.wallbase_newest_url
+ f = urllib.urlopen(self.final_url)
+ s = f.read()
+ counter = -1;
+ for line in s.split('\n'):
+ if('http://wallbase.cc/wallpaper/' in line):
+ value = line[line.find("http://wallbase.cc/wallpaper/"):line.find('" id="')]
+ #print value
+ ff = urllib.urlopen(value)
+ ss = ff.read()
+ for lline in ss.split('\n'):
+ if('<img src="http://' in lline) and ('.jpg' in lline) and (' alt=' in lline):
+ vvalue = lline[lline.find('<img src="http://')+10 :lline.find('" alt="')]
+ #print "::::::::::::::::::" + vvalue
+ counter = counter + 1
+ self.new_returnlist[str(counter)]= vvalue
+ #print self.new_returnlist
+ return self.new_returnlist
+ else:
+ return self.new_returnlist
+
+
+
+
+
+ def get_random_url(self):
+ if(len(self.ran_returnlist) <= 0 ):
+ self.final_url = self.wallbase_random_url
+ f = urllib.urlopen(self.final_url)
+ s = f.read()
+ counter = -1;
+ #p =re.compile("http://[^[:space:]]*")
+ for line in s.split('\n'):
+ if('http://wallbase.cc/wallpaper/' in line):
+ value = line[line.find("http://wallbase.cc/wallpaper/"):line.find('" id="')]
+ #print value
+ ff = urllib.urlopen(value)
+ ss = ff.read()
+ for lline in ss.split('\n'):
+ if('<img src="http://' in lline) and ('.jpg' in lline) and (' alt=' in lline):
+ vvalue = lline[lline.find('<img src="http://')+10 :lline.find('" alt="')]
+ #print "::::::::::::::::::" + vvalue
+ counter = counter + 1
+ self.ran_returnlist[str(counter)]= vvalue
+ #print self.ran_returnlist
+ return self.ran_returnlist
+ else:
+ return self.ran_returnlist
+
+
=== added file 'slidewall_engine/wallclock.py'
--- slidewall_engine/wallclock.py 1970-01-01 00:00:00 +0000
+++ slidewall_engine/wallclock.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,305 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+
+#Credit goes to Natan Yellin from WallpaperClockScreenlet.This module is based almost entirely on his work
+
+from gi.repository import Gtk
+import decimal
+import math
+import os
+import random
+import time
+import ConfigParser
+
+from slidewall_engine import ConfEngine
+from slidewall_engine import NotifyEngine
+
+from commands import getoutput
+from datetime import datetime
+from sys import path
+
+from gi.repository import Gio
+
+try:
+ import Image
+except:
+ import sys
+ print "Please make sure you have installed python image module"
+ sys.exit()
+
+class WallClock:
+ clock_settings = 'com.canonical.indicator.datetime'
+ def __init__(self,parent):
+ self.parent = parent
+ self.time = datetime.now()
+ self.timeout = None
+ self.dec = decimal.Decimal
+ self.image = None
+ self.image1 = None
+ self.current_file_index = 0
+
+ self.month = ''
+ self.day = ''
+ self.hour = ''
+ self.minute = ''
+ self.weekday = ''
+
+ self.settings = Gio.Settings.new(self.clock_settings)
+ self.hour_format = '12'
+ if(self.isFormat24()):
+ self.hour_format = '24'
+
+
+
+
+ def import_wallclock_dialog(self, parent = None):
+ ''' Show a dialog wich let you choose a .wcz file and install
+ it in /home/user/.local/share/slidewall/live/<name_of_the_wcz>'''
+
+ filter = Gtk.FileFilter()
+ filter.add_pattern('*.wcz')
+
+ dlg = Gtk.FileChooserDialog(buttons=(Gtk.STOCK_CANCEL,
+ Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+ dlg.set_current_folder(os.environ['HOME'])
+ dlg.set_title('Import Wallpaper Clock (.wcz package)')
+ dlg.set_filter(filter)
+
+ resp = dlg.run()
+ filename = dlg.get_filename()
+ dlg.destroy()
+ if resp == Gtk.ResponseType.OK:
+ self.install (filename)
+ #update livemode
+ self.clear_icon_view(parent.live_view, parent.live_engine)
+ parent.live_engine.load_livemode_wall()
+
+ def install(self,path):
+ """Extract the .wcz archive"""
+ filename = path
+ basename = os.path.basename(filename)
+ extension = str(filename)[-3:]
+
+ unzip_command = 'unzip -o %s -d %s'
+ config_engine = ConfEngine.ConfigEngine()
+ notify_engine = NotifyEngine.NotifyServer('Slidewall')
+ if extension.lower() == 'wcz':
+ if not os.path.isdir(self.parent.config_engine.slidewall_live_dir + '/' + basename):
+ os.mkdir(self.parent.config_engine.slidewall_live_dir + '/' + basename)
+ os.system(unzip_command % (chr(34) + filename + chr(34),
+ self.parent.config_engine.slidewall_live_dir + '/' + basename))
+ notify_engine.wall_notify('Slidewall','Wallpaper clock imported!',config_engine.slidewall_data+'/media/slidewall.png')
+ return True
+ else:
+ notify_engine.wall_notify('Slidewall','Wallpaper clock could not be imported!File must be invalid',config_engine.slidewall_data+'/media/slidewall.png')
+ return False
+
+ def clear_icon_view(self, iconview, live_engine):
+ '''Clear all the widgets from iconview '''
+ live_engine.remove_bin(widget = None, data = None)
+
+
+ def isFormat24(self):
+ '''Check if ubuntu time format is 24 hour'''
+ value = self.settings.get_string("time-format")
+ if value == '24-hour':
+ return True
+ return False
+ def position(self, now=None):
+ dec = decimal.Decimal
+ if now is None:
+ now = datetime.now()
+
+ diff = now - datetime(2001, 1, 1)
+ days = dec(diff.days) + (dec(diff.seconds) / dec(86400))
+ lunations = dec("0.20439731") + (days * dec("0.03386319269"))
+
+ return lunations % dec(1)
+
+ def phase(self, pos):
+ dec = decimal.Decimal
+ index = (pos * dec(8)) + dec("0.5")
+ index = math.floor(index)
+ return [("New Moon"),("Waxing Crescent"),("First Quarter"),("Waxing Gibbous"),("Full Moon"),("Waning Gibbous"),("Last Quarter"),("Waning Crescent")][int(index) & 7]
+
+ def get_zodiac(self, day, month):
+ """Finds the zodiac and returns it."""
+ # all zodiacs in order of the monthss
+ zodiac = [('Capricorn'), ('Aquarius'),
+ ('Pisces'), ('Aries'), ('Taurus'),
+ ('Gemini'), ('Cancer'), ('Leo'),
+ ('Virgo'), ('Libra'), ('Scorpio'),
+ ('Sagittarius')]
+
+ # the midpoints each month where one zodiac
+ # ends and the next begins, in month order
+ midpoint = [19, 18, 20, 19, 20,
+ 20, 22, 22, 22, 22, 21, 21]
+
+ # deal with december where we need to wrap
+ # around to the first zodiac
+ if month == 12 and day > midpoint[month-1]:
+ return zodiac[0]
+
+ # if it's the first half of the month,
+ # return the appropriate zodiac
+ elif day <= midpoint[month-1]:
+ return zodiac[month-1]
+
+ # if it's the second half of the month,
+ # return the next zodiac in the list
+ else:
+ return zodiac[month]
+
+ def get_day (self):
+ """Only needed for the service."""
+ return self.time.strftime("%d")
+
+ def get_month (self):
+ """Only needed for the service."""
+ return self.time.strftime("%m")
+
+ def get_hour24 (self):
+ """Only needed for the service."""
+ return self.time.strftime("%H")
+
+ def get_hour (self):
+ """Only needed for the service."""
+ if self.hour_format == '24' :
+ return self.time.strftime("%H")
+ elif self.hour_format == '12' :
+ return self.time.strftime("%I")
+
+ def get_minute (self):
+ """Only needed for the service."""
+ return self.time.strftime("%M")
+
+ def get_weekday (self):
+ """Only needed for the service."""
+ return self.time.strftime("%w")
+
+ def get_year (self):
+ """Only needed for the service."""
+ return self.time.strftime("%y")
+
+ def set_image(self,basename):
+ '''Build image and save it in /home/<user>/.local/share/slidewall/live/slidewall.png'''
+ #print "Point 1: " +str(time.localtime())
+ #print "Point 1: " +str(datetime.now())
+ if basename!= '':
+ # load the background image and determine the path
+ try:
+ self.image = Image.open( basename+'/bg.jpg')
+ path = basename
+ except:
+ self.parent.parent.notify_engine.wall_notify('WallClock cant find' + basename ,self.parent.config_engine.slidewall_data+'/media/slidewall.png')
+ path = ''
+
+ # load the am/pm image and paste it onto the background
+ if self.hour_format == '12' and os.path.isfile(path + '/am.png'):
+ print 'is 12 hour format and there is a am.png file'
+ try:
+ if int(self.get_hour24())> 12:
+ print 'setting pm'
+ self.image1 = Image.open(path + '/pm.png')
+ self.image.paste(self.image1, (0,0), self.image1)
+ else:
+ print 'setting am'
+ self.image1 = Image.open(path + '/am.png')
+ self.image.paste(self.image1, (0,0), self.image1)
+ #self.hour = str(int(self.hour)/2)
+ except:
+ try:
+ self.image1 = self.image1.convert('RGBA')
+ self.image.paste(self.image1, (0,0), self.image1)
+ except:
+ pass
+
+
+ # load the other images and paste them onto the background
+ for img in ("minute", "hour", "day", "month", "weekday"):
+ try:
+ self.image1 = Image.open(path + '/' + img + getattr(self, img) + '.png')
+ print('image::' + img)
+ self.image.paste(self.image1, (0,0), self.image1)
+ except:
+ try:
+ self.image1 = self.image1.convert('RGBA')
+ self.image.paste(self.image1, (0,0), self.image1)
+ except:
+ pass
+
+ # save the file to the location we just selected. this is a slow operation
+ self.image.save(self.parent.config_engine.slidewall_live_dir + '/slidewall.png')
+
+ def update(self,basename = None):
+ print 'WallClock::update()'
+ dec = decimal.Decimal
+
+ self.time = datetime.now()
+
+ self.minute = self.get_minute()
+ self.hour = self.get_hour()
+ self.day = self.get_day()
+ self.month = self.get_month()
+ self.year = self.get_year()
+
+ self.hour24 = self.get_hour24()
+ self.weekday = self.get_weekday()
+
+ pos = self.position()
+ self.moon = int(((float(pos))*100)/3.333333) +1
+ self.moon = str(self.moon)
+ phasename = self.phase(pos)
+ self.zodiac = self.get_zodiac(int(self.day),int(self.month))
+
+ config = ConfigParser.RawConfigParser()
+ config.read(basename+'/clock.ini')
+ refreshhourinterval = config.getint('Settings', 'refreshhourinterval')
+ hourimages = config.getint('Settings', 'hourimages')
+ ampmenabled = config.getint('Settings', 'ampmenabled')
+ if ampmenabled == 0:
+ self.hour = str(((int(self.hour24) * 60 + int(self.minute)) / refreshhourinterval) % hourimages)
+ elif ampmenabled == 1 and self.hour_format == '12':
+ self.hour = str(((int(self.hour) * 60 + int(self.minute)) / refreshhourinterval) % hourimages)
+
+ if self.month[0] == '0':
+ self.month = self.month[1]
+
+ if self.day[0] == '0':
+ self.day = self.day[1]
+
+ if self.hour[0] == '0':
+ if len(str(self.hour)) == 2:
+ self.hour = self.hour[1]
+ if len(str(self.hour)) == 1:
+ self.hour = self.hour[0]
+ if int(self.hour)>60:
+ self.hour = str(int(self.hour)-60)
+
+ if self.minute[0] == '0':
+ self.minute = self.minute[1]
+
+ if self.weekday == '0':
+ self.weekday = '7'
+
+ self.set_image (basename)
+ self.parent.wall_engine.set_wallpaper('file://' + self.parent.config_engine.slidewall_live_dir + '/slidewall.png')
+ self.parent.wall_engine.set_picture_options('stretched')
+ return True
+
+
=== added directory 'slidewall_lib'
=== added file 'slidewall_lib/AboutDialog.py'
--- slidewall_lib/AboutDialog.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/AboutDialog.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,48 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+from gi.repository import Gtk # pylint: disable=E0611
+
+from . helpers import get_builder
+
+class AboutDialog(Gtk.AboutDialog):
+ __gtype_name__ = "AboutDialog"
+
+ def __new__(cls):
+ """Special static method that's automatically called by Python when
+ constructing a new instance of this class.
+
+ Returns a fully instantiated AboutDialog object.
+ """
+ builder = get_builder('AboutSlidewallDialog')
+ new_object = builder.get_object("about_slidewall_dialog")
+ new_object.finish_initializing(builder)
+ return new_object
+
+ def finish_initializing(self, builder):
+ """Called while initializing this instance in __new__
+
+ finish_initalizing should be called after parsing the ui definition
+ and creating a AboutDialog object with it in order
+ to finish initializing the start of the new AboutSlidewallDialog
+ instance.
+
+ Put your initialization code in here and leave __init__ undefined.
+ """
+ # Get a reference to the builder and set up the signals.
+ self.builder = builder
+ self.ui = builder.get_ui(self)
+
=== added file 'slidewall_lib/Builder.py'
--- slidewall_lib/Builder.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/Builder.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,323 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+'''Enhances builder connections, provides object to access glade objects'''
+
+from gi.repository import GObject, Gtk # pylint: disable=E0611
+from gi.repository import AppIndicator3 as appindicator
+import inspect
+import functools
+import logging
+logger = logging.getLogger('slidewall_lib')
+
+from xml.etree.cElementTree import ElementTree
+
+# this module is big so uses some conventional prefixes and postfixes
+# *s list, except self.widgets is a dictionary
+# *_dict dictionary
+# *name string
+# ele_* element in a ElementTree
+
+
+# pylint: disable=R0904
+# the many public methods is a feature of Gtk.Builder
+class Builder(Gtk.Builder):
+ ''' extra features
+ connects glade defined handler to default_handler if necessary
+ auto connects widget to handler with matching name or alias
+ auto connects several widgets to a handler via multiple aliases
+ allow handlers to lookup widget name
+ logs every connection made, and any on_* not made
+ '''
+
+ def __init__(self):
+ Gtk.Builder.__init__(self)
+ self.widgets = {}
+ self.glade_handler_dict = {}
+ self.connections = []
+ self._reverse_widget_dict = {}
+
+# pylint: disable=R0201
+# this is a method so that a subclass of Builder can redefine it
+ def default_handler(self,
+ handler_name, filename, *args, **kwargs):
+ '''helps the apprentice guru
+
+ glade defined handlers that do not exist come here instead.
+ An apprentice guru might wonder which signal does what he wants,
+ now he can define any likely candidates in glade and notice which
+ ones get triggered when he plays with the project.
+ this method does not appear in Gtk.Builder'''
+ logger.debug('''tried to call non-existent function:%s()
+ expected in %s
+ args:%s
+ kwargs:%s''', handler_name, filename, args, kwargs)
+# pylint: enable=R0201
+
+ def get_name(self, widget):
+ ''' allows a handler to get the name (id) of a widget
+
+ this method does not appear in Gtk.Builder'''
+ return self._reverse_widget_dict.get(widget)
+
+ def add_from_file(self, filename):
+ '''parses xml file and stores wanted details'''
+ Gtk.Builder.add_from_file(self, filename)
+
+ # extract data for the extra interfaces
+ tree = ElementTree()
+ tree.parse(filename)
+
+ ele_widgets = tree.getiterator("object")
+ for ele_widget in ele_widgets:
+ name = ele_widget.attrib['id']
+ widget = self.get_object(name)
+
+ # populate indexes - a dictionary of widgets
+ self.widgets[name] = widget
+
+ # populate a reversed dictionary
+ self._reverse_widget_dict[widget] = name
+
+ # populate connections list
+ ele_signals = ele_widget.findall("signal")
+
+ connections = [
+ (name,
+ ele_signal.attrib['name'],
+ ele_signal.attrib['handler']) for ele_signal in ele_signals]
+
+ if connections:
+ self.connections.extend(connections)
+
+ ele_signals = tree.getiterator("signal")
+ for ele_signal in ele_signals:
+ self.glade_handler_dict.update(
+ {ele_signal.attrib["handler"]: None})
+
+ def connect_signals(self, callback_obj):
+ '''connect the handlers defined in glade
+
+ reports successful and failed connections
+ and logs call to missing handlers'''
+ filename = inspect.getfile(callback_obj.__class__)
+ callback_handler_dict = dict_from_callback_obj(callback_obj)
+ connection_dict = {}
+ connection_dict.update(self.glade_handler_dict)
+ connection_dict.update(callback_handler_dict)
+ for item in connection_dict.items():
+ if item[1] is None:
+ # the handler is missing so reroute to default_handler
+ handler = functools.partial(
+ self.default_handler, item[0], filename)
+
+ connection_dict[item[0]] = handler
+
+ # replace the run time warning
+ logger.warn("expected handler '%s' in %s",
+ item[0], filename)
+
+ # connect glade define handlers
+ Gtk.Builder.connect_signals(self, connection_dict)
+
+ # let's tell the user how we applied the glade design
+ for connection in self.connections:
+ widget_name, signal_name, handler_name = connection
+ logger.debug("connect builder by design '%s', '%s', '%s'",
+ widget_name, signal_name, handler_name)
+
+ def get_ui(self, callback_obj=None, by_name=True):
+ '''Creates the ui object with widgets as attributes
+
+ connects signals by 2 methods
+ this method does not appear in Gtk.Builder'''
+
+ result = UiFactory(self.widgets)
+
+ # Hook up any signals the user defined in glade
+ if callback_obj is not None:
+ # connect glade define handlers
+ self.connect_signals(callback_obj)
+
+ if by_name:
+ auto_connect_by_name(callback_obj, self)
+
+ return result
+
+
+# pylint: disable=R0903
+# this class deliberately does not provide any public interfaces
+# apart from the glade widgets
+class UiFactory():
+ ''' provides an object with attributes as glade widgets'''
+ def __init__(self, widget_dict):
+ self._widget_dict = widget_dict
+ for (widget_name, widget) in widget_dict.items():
+ setattr(self, widget_name, widget)
+
+ # Mangle any non-usable names (like with spaces or dashes)
+ # into pythonic ones
+ cannot_message = """cannot bind ui.%s, name already exists
+ consider using a pythonic name instead of design name '%s'"""
+ consider_message = """consider using a pythonic name instead of design name '%s'"""
+
+ for (widget_name, widget) in widget_dict.items():
+ pyname = make_pyname(widget_name)
+ if pyname != widget_name:
+ if hasattr(self, pyname):
+ logger.debug(cannot_message, pyname, widget_name)
+ else:
+ logger.debug(consider_message, widget_name)
+ setattr(self, pyname, widget)
+
+ def iterator():
+ '''Support 'for o in self' '''
+ return iter(widget_dict.values())
+ setattr(self, '__iter__', iterator)
+
+ def __getitem__(self, name):
+ 'access as dictionary where name might be non-pythonic'
+ return self._widget_dict[name]
+# pylint: enable=R0903
+
+
+def make_pyname(name):
+ ''' mangles non-pythonic names into pythonic ones'''
+ pyname = ''
+ for character in name:
+ if (character.isalpha() or character == '_' or
+ (pyname and character.isdigit())):
+ pyname += character
+ else:
+ pyname += '_'
+ return pyname
+
+
+# Until bug https://bugzilla.gnome.org/show_bug.cgi?id=652127 is fixed, we
+# need to reimplement inspect.getmembers. GObject introspection doesn't
+# play nice with it.
+def getmembers(obj, check):
+ members = []
+ for k in dir(obj):
+ try:
+ attr = getattr(obj, k)
+ except:
+ continue
+ if check(attr):
+ members.append((k, attr))
+ members.sort()
+ return members
+
+
+def dict_from_callback_obj(callback_obj):
+ '''a dictionary interface to callback_obj'''
+ methods = getmembers(callback_obj, inspect.ismethod)
+
+ aliased_methods = [x[1] for x in methods if hasattr(x[1], 'aliases')]
+
+ # a method may have several aliases
+ #~ @alias('on_btn_foo_clicked')
+ #~ @alias('on_tool_foo_activate')
+ #~ on_menu_foo_activate():
+ #~ pass
+ alias_groups = [(x.aliases, x) for x in aliased_methods]
+
+ aliases = []
+ for item in alias_groups:
+ for alias in item[0]:
+ aliases.append((alias, item[1]))
+
+ dict_methods = dict(methods)
+ dict_aliases = dict(aliases)
+
+ results = {}
+ results.update(dict_methods)
+ results.update(dict_aliases)
+
+ return results
+
+
+def auto_connect_by_name(callback_obj, builder):
+ '''finds handlers like on_<widget_name>_<signal> and connects them
+
+ i.e. find widget,signal pair in builder and call
+ widget.connect(signal, on_<widget_name>_<signal>)'''
+
+ callback_handler_dict = dict_from_callback_obj(callback_obj)
+
+ for item in builder.widgets.items():
+ (widget_name, widget) = item
+ signal_ids = []
+ try:
+ widget_type = type(widget)
+ while widget_type:
+ signal_ids.extend(GObject.signal_list_ids(widget_type))
+ widget_type = GObject.type_parent(widget_type)
+ except RuntimeError: # pylint wants a specific error
+ pass
+ signal_names = [GObject.signal_name(sid) for sid in signal_ids]
+
+ # Now, automatically find any the user didn't specify in glade
+ for sig in signal_names:
+ # using convention suggested by glade
+ sig = sig.replace("-", "_")
+ handler_names = ["on_%s_%s" % (widget_name, sig)]
+
+ # Using the convention that the top level window is not
+ # specified in the handler name. That is use
+ # on_destroy() instead of on_windowname_destroy()
+ if widget is callback_obj:
+ handler_names.append("on_%s" % sig)
+
+ do_connect(item, sig, handler_names,
+ callback_handler_dict, builder.connections)
+
+ log_unconnected_functions(callback_handler_dict, builder.connections)
+
+
+def do_connect(item, signal_name, handler_names,
+ callback_handler_dict, connections):
+ '''connect this signal to an unused handler'''
+ widget_name, widget = item
+
+ for handler_name in handler_names:
+ target = handler_name in callback_handler_dict.keys()
+ connection = (widget_name, signal_name, handler_name)
+ duplicate = connection in connections
+ if target and not duplicate:
+ widget.connect(signal_name, callback_handler_dict[handler_name])
+ connections.append(connection)
+
+ logger.debug("connect builder by name '%s','%s', '%s'",
+ widget_name, signal_name, handler_name)
+
+
+def log_unconnected_functions(callback_handler_dict, connections):
+ '''log functions like on_* that we could not connect'''
+
+ connected_functions = [x[2] for x in connections]
+
+ handler_names = callback_handler_dict.keys()
+ unconnected = [x for x in handler_names if x.startswith('on_')]
+
+ for handler_name in connected_functions:
+ try:
+ unconnected.remove(handler_name)
+ except ValueError:
+ pass
+
+ for handler_name in unconnected:
+ logger.debug("Not connected to builder '%s'", handler_name)
=== added file 'slidewall_lib/Window.py'
--- slidewall_lib/Window.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/Window.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,762 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+from gi.repository import Gio, Gtk,Gdk,GdkPixbuf,GObject # pylint: disable=E0611
+from gi.repository import AppIndicator3 as appindicator
+from slidewall_engine import ConfEngine
+from slidewall_engine import SlideWallEngine
+from slidewall_engine import NotifyEngine
+from slidewall_engine import wallbase
+from slidewall_engine import liveengine
+from slidewall_engine import wallclock
+import logging
+import os
+import urllib
+logger = logging.getLogger('slidewall_lib')
+
+from . helpers import get_builder, show_uri, get_help_uri
+
+# This class is meant to be subclassed by SlidewallWindow. It provides
+# common functions and some boilerplate.
+class Window(Gtk.Window):
+ __gtype_name__ = "Window"
+
+ # To construct a new instance of this method, the following notable
+ # methods are called in this order:
+ # __new__(cls)
+ # __init__(self)
+ # finish_initializing(self, builder)
+ # __init__(self)
+ #
+ # For this reason, it's recommended you leave __init__ empty and put
+ # your initialization code in finish_initializing
+
+ def __new__(cls):
+ """Special static method that's automatically called by Python when
+ constructing a new instance of this class.
+
+ Returns a fully instantiated BaseSlidewallWindow object.
+ """
+ builder = get_builder('SlidewallWindow')
+ new_object = builder.get_object("slidewall_window")
+ new_object.finish_initializing(builder)
+ return new_object
+
+ def finish_initializing(self, builder):
+ """Called while initializing this instance in __new__
+
+ finish_initializing should be called after parsing the UI definition
+ and creating a SlidewallWindow object with it in order to finish
+ initializing the start of the new SlidewallWindow instance.
+ """
+ #copy first the data
+ self.config_engine = ConfEngine.ConfigEngine()
+ self.live_engine = liveengine.LiveEngine(parent = self)
+ # Get a reference to the builder and set up the signals.
+ self.builder = builder
+ self.ui = builder.get_ui(self, True)
+
+ self.AboutDialog = None # class
+
+ self.settings = Gio.Settings("net.launchpad.slidewall")
+
+ self.first_start = True
+ if(os.path.exists(os.environ['HOME'] + '/.local/share/slidewall')):
+ self.first_start = False
+ #enable buttons with images on them
+ bt_settings = Gtk.Settings.get_default()
+ bt_settings.props.gtk_button_images = True
+ bt_settings.props.gtk_menu_images = True
+
+ self.wall_engine = SlideWallEngine.WallEngine()
+ self.notify_engine = NotifyEngine.NotifyServer('Slidewall')
+ self.wall_base = wallbase.WallBase()
+ self.slide_link={}
+ self.livemode_position = 'live earth'
+ self.ui.cb_options.set_active(0)
+ self.slide_options = {'0':'zoom','1':'scaled','2':'centered','3':'spanned','4':'stretched','5':'wallpaper'}
+
+
+ # Optional Launchpad integration
+ # This shouldn't crash if not found as it is simply used for bug reporting.
+ # See https://wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding
+ # for more information about Launchpad integration.
+ try:
+ from gi.repository import LaunchpadIntegration # pylint: disable=E0611
+ LaunchpadIntegration.add_items(self.ui.helpMenu, 1, True, True)
+ LaunchpadIntegration.set_sourcepackagename('slidewall')
+ except ImportError:
+ pass
+
+ # Optional application indicator support
+ # Run 'quickly add indicator' to get started.
+ # More information:
+ # http://owaislone.org/quickly-add-indicator
+ # https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators
+ #try:
+ #from slidewall import indicator
+ # self is passed so methods of this class can be called from indicator.py
+ # Comment this next line out to disable appindicator
+ #self.indicator = indicator.new_application_indicator(self)
+ #except ImportError:
+ #pass
+ self.position = 0
+ self.livemode_last = 0
+
+ self.timer_id = 1
+ self.liststore2 = Gtk.ListStore(GdkPixbuf.Pixbuf,str)
+ self.liststore3 = Gtk.ListStore(GdkPixbuf.Pixbuf,str)
+
+ self.live_engine.load_livemode_wall()
+ self.wallclock_engine = wallclock.WallClock(parent = self)
+ #force write config file
+ if(self.first_start):
+ self.on_bt_save_clicked(None)
+
+ self.load_config_file()
+ self.ui.wall_view.set_pixbuf_column(0)
+ self.ui.wall_view.set_text_column(1)
+ print(str(self.first_start))
+ if(self.ui.r_bt_slide.get_active() and (not self.first_start) ):
+ print("Going to autostart slideshow")
+ #initialize timer_id but won't run now since 1 billion seconds it's quite a time
+ self.timer_id = GObject.timeout_add_seconds(1000000000,self.on_slidechange_time,None)
+ #now force running in the background
+ self.on_bt_start_clicked(self.ui.bt_start)
+
+
+ elif(not self.first_start) :
+ print("Going to autostart live")
+ self.timer_id = GObject.timeout_add_seconds(1000000000,self.on_livechange_time,None)
+ #now force autostart in livemode
+ self.on_bt_apply_clicked(self.ui.bt_apply, data = [self.livemode_position])
+
+ #force starting in system tray if check_tray is active
+ if(self.ui.check_tray.get_active() and not self.first_start):
+ #self.ui.slidewall_window.hide()
+ self.ui.slidewall_window.iconify()
+ self.build_tray()
+ self.build_tray_first = 1
+
+ def on_mnu_contents_activate(self, widget, data=None):
+ show_uri(self, "ghelp:%s" % get_help_uri())
+
+ def on_mnu_about_activate(self, widget, data=None):
+ """Display the about box for slidewall."""
+ if self.AboutDialog is not None:
+ about = self.AboutDialog() # pylint: disable=E1102
+ response = about.run()
+ about.destroy()
+
+ def on_mnu_close_activate(self, widget, data=None):
+ """Signal handler for closing the SlidewallWindow."""
+ print("menu close activated")
+ self.on_bt_close_clicked(widget)
+ def on_delete_event(self,widget,data=None):
+ ret = self.on_bt_close_clicked(widget)
+ return ret
+
+ def on_destroy(self, widget, data=None):
+ """Called when the SlidewallWindow is closed."""
+ self.on_bt_close_clicked(None)
+
+
+ def on_preferences_changed(self, settings, key, data=None):
+ logger.debug('preference changedpython check if is file: %s = %s' % (key, str(settings.get_value(key))))
+
+ def on_preferences_dialog_destroyed(self, widget, data=None):
+ '''only affects gui
+
+ logically there is no difference between the user closing,
+ minimising or ignoring the preferences dialog'''
+ logger.debug('on_preferences_dialog_destroyed')
+ # to determine whether to create or present preferences_dialog
+ self.preferences_dialog = None
+ def slide_togled(self,widget,data=None):
+ ''' when slideshow mode is togled than
+ activate the timing_box'''
+ logger.debug("SlideShow Mode activated")
+ if(self.ui.r_bt_slide.get_active()):
+ self.ui.timing_box.set_sensitive(True)
+ elif(self.ui.r_bt_live.get_active()):
+ self.ui.timing_box.set_sensitive(False)
+
+ def on_bt_quit_clicked(self,widget,data=None):
+ '''when this button is clicked we should save all
+ the app info and call gtk_main_quit
+ '''
+ #save data
+ logger.debug("Going to quit the app")
+ self.save_data_on_quit()
+ Gtk.main_quit()
+
+ def tray_view(self,widget,data=None):
+ logger.debug("Showing SlideWall")
+ print('tray_view::running tray_view')
+ if(self.build_tray_first):
+ self.build_tray_first = False
+ self.ui.slidewall_window.show()
+ else:
+ self.ui.slidewall_window.show()
+ self.ui.slidewall_window.deiconify()
+ self.ui.bt_close.set_sensitive(True)
+ print('tray_view::running tray_view')
+
+
+ if(os.path.exists('/usr/share/icons/hicolor/48x48/apps/slidewall.png')):
+ self.icon_pixbuf = GdkPixbuf.Pixbuf.new_from_file('/usr/share/icons/hicolor/48x48/apps/slidewall.png')
+ else:
+ self.icon_pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.config_engine.slidewall_data + '/media/slidewall.png')
+ self.ui.slidewall_window.set_icon(self.icon_pixbuf)
+
+ def tray_exit(self,widget,data=None):
+ logger.debug("Going to close SlideWall")
+ self.save_data_on_quit()
+ Gtk.main_quit()
+
+ def tray_icon_activated(self,widget,data=None):
+ self.ui.slidewall_window.hide()
+ self.ui.slidewall_window.iconify()
+
+ def tray_icon_popup(self,menu):
+ menu.popup()
+
+ def build_tray(self):
+ '''This method build the system try indicator for slidewalls'''
+ print('Build_tray:::called()')
+ self.tray_indicator = appindicator.Indicator.new ("slidewall",'',appindicator.IndicatorCategory.APPLICATION_STATUS)
+ self.tray_indicator.set_status (appindicator.IndicatorStatus.ACTIVE)
+
+ self.tray_indicator.set_icon (self.config_engine.slidewall_data + '/media/slidewall.png')
+ #agr = GtkAccelGroup().new()
+ #self.ui.slidewall_window.add_accel_group(agr)
+
+ self.__menu_tray = Gtk.Menu()
+
+ self.menu_item_view = Gtk.ImageMenuItem("View SlideWall")
+ self.menu_item_view.set_image(self.ui.img_view)
+ self.menu_item_view.connect("activate",self.tray_view,self.ui)
+ self.menu_item_view.show()
+ self.__menu_tray.append(self.menu_item_view)
+
+ self.menu_item_prev = Gtk.ImageMenuItem("Previous")
+ self.menu_item_prev.set_image(self.ui.img_prev)
+ self.menu_item_prev.connect("activate",self.on_menu_prev,self.ui)
+ self.menu_item_prev.show()
+ self.__menu_tray.append(self.menu_item_prev)
+
+ self.menu_item_next = Gtk.ImageMenuItem("Next")
+ self.menu_item_next.set_image(self.ui.img_next)
+ self.menu_item_next.connect("activate",self.on_menu_next,self.ui)
+ self.menu_item_next.show()
+ self.__menu_tray.append(self.menu_item_next)
+
+ self.menu_item_exit = Gtk.ImageMenuItem("Exit SlideWall")
+ self.menu_item_exit.set_image(self.ui.img_quit)
+ self.menu_item_exit.connect("activate",self.tray_exit,self.ui)
+ self.menu_item_exit.show()
+ self.__menu_tray.append(self.menu_item_exit)
+
+
+
+
+
+
+ self.__menu_tray.show()
+ self.tray_indicator.set_menu(self.__menu_tray)
+
+
+ def on_bt_close_clicked(self,widget,data=None):
+ '''Define actions to do when button Close to Tray/system Close is pressed'''
+ print('on_bt_close_clicked')
+ if(self.ui.check_tray.get_active()):
+ self.ui.bt_close.set_sensitive(False)
+ self.ui.slidewall_window.hide()
+ self.ui.slidewall_window.iconify()
+ self.build_tray()
+ return True
+ else:
+ self.save_data_on_quit()
+ Gtk.main_quit()
+ return False
+
+ def on_bt_reset_clicked(self,widget,data=None):
+ '''Reset user preferences to default'''
+ logger.debug("Reset user preferences to default")
+ self.ui.r_bt_slide.set_active(True)
+ self.ui.r_bt_live.set_active(False)
+ self.ui.adjustment3.set_value(2.5)
+ self.ui.check_tray.set_active(True)
+ self.ui.check_notify.set_active(True)
+
+ def load_config_file(self):
+ '''Load user preferences.Must be called in constructor'''
+ logger.debug('Loading user preferences')
+ # read preferences config file
+ data = self.config_engine.read_config(self.config_engine.slidewall_conf_file)
+ if (len(data) >0):
+ self.ui.r_bt_slide.set_active(data['r_bt_slide'])
+ self.ui.r_bt_live.set_active(data['r_bt_live'])
+ self.ui.adjustment3.set_value(data['adjustment3']) #minutes
+ self.ui.adjustment2.set_value(data['adjustment2']) #seconds
+ self.ui.check_tray.set_active(data['check_tray'])
+ self.ui.check_notify.set_active(data['check_notify'])
+ #read slideshow mode config file
+ image_list = []
+ self.slide_config = self.config_engine.read_config(self.config_engine.slidemode_conf_file)
+ for iterr in self.slide_config:
+ if not(iterr =='position') and not(iterr=='option'):
+ image_list =image_list + [self.slide_config[iterr] ]
+ self.ui.wall_view.freeze_child_notify()
+ self.ui.wall_view.set_model(None)
+
+ self.fill_store_from_image_list(image_list)
+
+ self.ui.wall_view.set_model(self.liststore2)
+ self.ui.wall_view.thaw_child_notify()
+ if len(self.slide_config)>0:
+ self.ui.cb_options.set_active(self.slide_config['option'])
+ self.position = self.slide_config['position']
+ #read live mode config file
+ self.live_config = self.config_engine.read_config(self.config_engine.livemode_conf_file)
+ if(len(self.live_config) > 0):
+ self.livemode_position = self.live_config['position']
+ else:
+ self.livemode_position = "live earth"
+
+ def on_bt_save_clicked(self,widget,data=None):
+ '''Save user preferences'''
+ logger.debug('Saving user preferences')
+ config_dict={}
+
+ config_dict['r_bt_slide'] = self.ui.r_bt_slide.get_active()
+ config_dict['r_bt_live'] = self.ui.r_bt_live.get_active()
+ #minutes
+ config_dict['adjustment3'] = self.ui.adjustment3.get_value()
+ #seconds
+ config_dict['adjustment2'] = self.ui.adjustment2.get_value()
+ config_dict['check_tray'] = self.ui.check_tray.get_active()
+ config_dict['check_notify'] = self.ui.check_notify.get_active()
+
+ self.config_engine.write_config(config_dict)
+ if(self.ui.check_autostart.get_active() ):
+ self.set_autostart()
+ elif(os.path.exists(self.config_engine.home_dir + '/.config/autostart/slidewall.desktop')):
+ os.remove(self.config_engine.home_dir + '/.config/autostart/slidewall.desktop')
+
+
+ def fill_store_from_dir(self,folder_path):
+ '''Fill up wall_view with image thumbnails from folder_path'''
+
+ if not (folder_path[len(folder_path) - 1] == '/'):
+ folder_path = folder_path + '/'
+
+ image_list = os.listdir(folder_path)
+ for image in image_list:
+ if os.path.isfile(folder_path + image):
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(folder_path+image,64,64)
+
+ self.liststore2.append([pixbuf,str(image)])
+ self.slide_link[str(image)] = folder_path + image
+ except Exception:
+ logger.debug(image + ' is not a image type')
+ else:
+ print("Can't add:" + folder_path+image)
+
+ def fill_store_from_image_list(self,image_list):
+ '''Fill up wall_view with image thumbnails from image_list'''
+ for image in image_list:
+ if os.path.isfile(image):
+ try:
+ pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(image,64,64)
+ basename = os.path.basename(image)
+ self.liststore2.append([pixbuf,str(basename)])
+ self.slide_link[basename] = image
+ except Exception:
+ logger.debug(image + ' is not a image type')
+ else:
+ print("Can't add:" + image)
+
+ def on_bt_select_files_clicked(self,widget,data=None):
+ '''Get a list with selected files and call fill_store_from_list'''
+ dialog = Gtk.FileChooserDialog("Please select one or more image files", self,Gtk.FileChooserAction.OPEN,(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+ dialog.set_select_multiple(True)
+ filter = Gtk.FileFilter()
+ filter.set_name("Images")
+ filter.add_mime_type("image/png")
+ filter.add_mime_type("image/jpeg")
+ filter.add_mime_type("image/jpg")
+ filter.add_mime_type("image/bmp")
+ filter.add_mime_type("image/gif")
+ filter.add_pattern("*.png")
+ filter.add_pattern("*.jpg")
+ filter.add_pattern("*.jpeg")
+ filter.add_pattern("*.bmp")
+ filter.add_pattern("*.gif")
+ filter.add_pattern("*.tif")
+ filter.add_pattern("*.xpm")
+ dialog.add_filter(filter)
+ response = dialog.run()
+ img_list = []
+ if response == Gtk.ResponseType.OK:
+ img_list=dialog.get_filenames()
+ dialog.destroy()
+ self.ui.wall_view.freeze_child_notify()
+ self.ui.wall_view.set_model(None)
+
+ self.fill_store_from_image_list(img_list)
+
+ self.ui.wall_view.set_model(self.liststore2)
+ self.ui.wall_view.thaw_child_notify()
+
+ def on_bt_select_folder_clicked(self,widget,data=None):
+ '''Get a list with selected folder and call fill_store_from_dir'''
+ dialog = Gtk.FileChooserDialog("Please select a folder wich contains image files", self,Gtk.FileChooserAction.SELECT_FOLDER,(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+ response = dialog.run()
+ folder_list=''
+ if response == Gtk.ResponseType.OK:
+ folder_list=dialog.get_filename()
+ print('Selected folder:' + folder_list)
+ dialog.destroy()
+ self.ui.wall_view.freeze_child_notify()
+ self.ui.wall_view.set_model(None)
+ self.fill_store_from_dir(folder_list)
+ self.ui.wall_view.set_model(self.liststore2)
+ self.ui.wall_view.thaw_child_notify()
+
+ def on_bt_delete_clicked(self,widget,data=None):
+ '''Remove selected items from iconview and from slide_link'''
+ if('timer_id' in vars(self) or 'timer_id' in globals()) and(self.ui.r_bt_slide.get_active()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ logger.debug('on_bt_delete_clicked::timer removed')
+ selects = self.ui.wall_view.get_selected_items()
+ for select in selects:
+ iterr = self.liststore2.get_iter(select)
+ datas = self.liststore2.get(iterr,0,1)
+ del self.slide_link[str(datas[1])]
+ self.liststore2.remove(iterr)
+
+ def on_cb_options_changed(self,widget,data=None):
+ '''Select wallpaper options '''
+ tree_iter = self.ui.cb_options.get_active_iter()
+ if tree_iter != None:
+ model = self.ui.cb_options.get_model()
+ option = model[tree_iter][0]
+ #set the image for image6 object
+ file_icon = self.config_engine.slidewall_data + '/media/monitor/monitor_' + option.lower() + '.png'
+ self.ui.image6.set_from_pixbuf( GdkPixbuf.Pixbuf.new_from_file(file_icon))
+
+ def on_menu_next(self,widget,data =None):
+ #next wallpaper
+ if(self.ui.r_bt_slide.get_active()):
+ #check if position is not greatear than len(self.slide_link)
+ if(self.position == (len(self.slide_link) - 1)):
+ self.position = 0;
+ else:
+ self.position = self.position +1
+ #get the wallpaper path
+ key = self.wall_dict[str(self.position)]
+ wallpaper = self.slide_link[key]
+ #print 'position::' + str(self.position) + ' new wallpaper::' + wallpaper + ' number of photos::' + str(len(self.slide_link))
+ self.wall_engine.set_wallpaper('file://' + wallpaper)
+ index = self.ui.cb_options.get_active()
+ self.wall_engine.set_picture_options(self.slide_options[str(index)])
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall',key + ' is your new wallpaper!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ else:
+ self.on_livechange_time(None)
+
+ def on_menu_prev(self,widget,data=None):
+ #previous wallpaper
+ if(self.ui.r_bt_slide.get_active()):
+ #check if position is not greatear than len(self.slide_link)
+ if(self.position == 0):
+ self.position = (len(self.slide_link) - 1)
+ else:
+ self.position = self.position -1
+ #get the wallpaper path
+ key = self.wall_dict[str(self.position)]
+ wallpaper = self.slide_link[key]
+ #print 'position::' + str(self.position) + ' new wallpaper::' + wallpaper + ' number of photos::' + str(len(self.slide_link))
+ self.wall_engine.set_wallpaper('file://' + wallpaper)
+ index = self.ui.cb_options.get_active()
+ self.wall_engine.set_picture_options(self.slide_options[str(index)])
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall',key + ' is your new wallpaper!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ else:
+ self.on_livechange_time(None)
+
+
+
+ def on_slidechange_time(self,user_data=None):
+ '''Change the wallpaper for slideshow mode'''
+ #print('position::' + str(self.position))
+ #check if position is not greatear than len(self.slide_link)
+ if(self.position == (len(self.slide_link) - 1)):
+ self.position = 0;
+ else:
+ self.position = self.position +1
+ #get the wallpaper path
+ key = self.wall_dict[str(self.position)]
+ wallpaper = self.slide_link[key]
+ print 'position::' + str(self.position) + ' new wallpaper::' + wallpaper + ' number of photos::' + str(len(self.slide_link))
+ self.wall_engine.set_wallpaper('file://' + wallpaper)
+ index = self.ui.cb_options.get_active()
+ print str(index)
+ if(index ==-1):
+ index = 0;
+ self.ui.cb_options.set_active(index)
+ self.wall_engine.set_picture_options(self.slide_options[str(index)])
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall',key + ' is your new wallpaper!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ return True
+
+ def on_livechange_time(self,user_data):
+ '''Change the wallpaper for the live mode'''
+ opt = self.livemode_position
+ print str(opt)
+ if(str(opt).isdigit() or (opt == None)):
+ opt = 'live earth'
+ self.livemode_position = 'live earth'
+ livemode_path = self.config_engine.home_dir + '/' + self.config_engine.share_dir + '/slidewall/live/slidewall.jpg'
+ print("livemode_path:::::" + livemode_path)
+ #sunlight wallpaper
+ if(opt == 'live earth'):
+ #download wallpaper and save it on /home/user/.local/share/slidewall/live/slidewallslidemode.jpg
+ try:
+ url = urllib.urlopen('http://www.opentopia.com/images/data/sunlight/world_sunlight_map_rectangular.jpg')
+ buff = url.read()
+ stream = open(livemode_path,'w')
+ stream.write(buff)
+ #set wallpaper
+ self.wall_engine.set_wallpaper('file://' + livemode_path)
+ self.wall_engine.set_picture_options('zoom')
+ return True
+ except Exception:
+ self.notify_engine.wall_notify('Slidewall','Please check your internet connection!\nPerhaps maybe opentopia.com is down!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ return None
+ elif(opt == 'new wallbase'):
+ #download wallpaper and save it on /home/user/.local/share/slidewall/live/slidewallslidemode.jpg
+ current = 0
+
+ try:
+ self.livemode_list = self.wall_base.get_newest_url();
+ if(self.livemode_last == len(self.livemode_list) - 1):
+ self.livemode_last = 0
+ else :
+ self.livemode_last = self.livemode_last + 1
+ print('url:::' + self.livemode_list[str(self.livemode_last)])
+ url = urllib.urlopen(self.livemode_list[str(self.livemode_last)])
+ buff = url.read()
+ stream = open(livemode_path,'w')
+ stream.write(buff)
+ #set wallpaper
+ self.wall_engine.set_wallpaper('file://' + livemode_path)
+ self.wall_engine.set_picture_options('zoom')
+ return True
+ except Exception:
+ self.notify_engine.wall_notify('Slidewall','Please check your internet connection!\nOr maybe wallbase.cc is down!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ return None
+ elif(opt == 'random wallbase' ):
+ #download wallpaper and save it on /home/user/.local/share/slidewall/live/slidewallslidemode.jpg
+ current = 0
+ try:
+ self.livemode_list = self.wall_base.get_random_url();
+ if(self.livemode_last == len(self.livemode_list) - 1):
+ self.livemode_last = 0
+ else :
+ self.livemode_last = self.livemode_last + 1
+ url = urllib.urlopen(self.livemode_list[str(self.livemode_last)])
+ buff = url.read()
+ stream = open(livemode_path,'w')
+ stream.write(buff)
+ #set wallpaper
+ print("on_livechange_time::" + str(self.livemode_last) + self.livemode_list[str(self.livemode_last)])
+ self.wall_engine.set_wallpaper('file://' + livemode_path)
+ self.wall_engine.set_picture_options('zoom')
+ return True
+ except Exception:
+ self.notify_engine.wall_notify('Slidewall','Please check your internet connection!\nOr maybe wallbase.cc is down!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ return None
+ else:
+ print 'Window::livechange()::called'
+ self.wallclock_engine.update(basename = self.live_engine.storee[opt])
+ return True
+
+
+
+ def on_bt_start_clicked(self,widget,data=None):
+ '''start the slideshow'''
+ self.ui.r_bt_slide.set_active(True)
+ if(len(self.slide_link) <=0):
+ # dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR,Gtk.ButtonsType.OK, "SlideWall Error")
+ # dialog.format_secondary_text("You need at least one image!")
+ # dialog.run()
+ # dialog.destroy()
+ return None
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+
+ #compute seconds
+ seconds = self.ui.adjustment3.get_value() * 60
+ seconds = seconds + self.ui.adjustment2.get_value()
+ #build position iterator
+ count = -1
+ self.wall_dict = {}
+ for key in self.slide_link:
+ count = count + 1
+ self.wall_dict[str(count)] = key
+ print('Going to change wallpaper at every::' + str(seconds) + ' seconds' + ' position::' + str(self.position))
+ #force on_slidechange_time first
+ if(int(seconds)< 40):
+ dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.WARNING,Gtk.ButtonsType.OK, "SlideWall Warning")
+ dialog.format_secondary_text("Because of performance reasons SlideShow Mode can't have a timer below 40 seconds")
+ dialog.run()
+ dialog.destroy()
+ seconds = 40
+ self.ui.adjustment3.set_value(0)
+ self.ui.adjustment2.set_value(40)
+
+
+ self.on_slidechange_time(None)
+ self.timer_id = GObject.timeout_add_seconds(int(seconds),self.on_slidechange_time,None)
+
+
+ def save_data_on_quit(self):
+ self.on_bt_save_clicked(None)
+ #remove timer if it is running
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ #save self.slide_config
+ self.slide_config={}
+ self.slide_config['position'] = self.position
+ self.slide_config['option'] = self.ui.cb_options.get_active()
+ self.slide_config = dict(self.slide_config.items() + self.slide_link.items() )
+ self.config_engine.write_config_in_file(self.slide_config,self.config_engine.slidemode_conf_file)
+
+ #save live mode
+ self.live_config = {}
+ #get the selected option
+ self.live_config['position'] = self.livemode_position
+ self.config_engine.write_config_in_file(self.live_config,self.config_engine.livemode_conf_file)
+
+
+ def on_live_view_clicked(self,widget,data=None):
+ datas = self.live_engine.get_selected()
+ textbuffer = self.ui.text_info.get_buffer()
+ if(datas == 'live earth'):
+ textbuffer.set_text("This option check every 20 minutes www.opentopia.com for the sunlight map.")
+ elif(datas == 'new wallbase'):
+ textbuffer.set_text("This option check every 15 minutes www.wallbase.cc for the newest wallpapers.")
+ elif(datas =='random wallbase'):
+ textbuffer.set_text("This option check every 15 minutes www.wallbase.cc for random wallpapers.")
+ else:
+ textbuffer.set_text("This wallpaper clock will be changing every minute.")
+
+ def on_bt_apply_clicked(self,widget,data=None):
+ self.ui.r_bt_live.set_active(True)
+ if( data != None ):
+ self.livemode_position = data[0]
+ else :
+ self.livemode_position = self.live_engine.get_selected()
+ opt = self.livemode_position
+ print(opt)
+ if(opt == 'live earth'):
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ print("Sending notification 0!")
+ self.notify_engine.wall_notify('Slidewall','Slidewall will update every 20 minutes your sunlight map',self.config_engine.slidewall_data+'/media/slidewall.png')
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+
+ self.on_livechange_time(None)
+ self.timer_id = GObject.timeout_add_seconds(1200,self.on_livechange_time,None) #20 minutes
+
+ elif(opt == 'new wallbase'):
+ print("Sending notification 1!")
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall','Slidewall will set every 15 minutes the newest wallpaper from wallbase.cc\nIf it is the first time you run this option on this session please be patient,it will take a while!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ self.on_livechange_time(None)
+ self.timer_id = GObject.timeout_add_seconds(900,self.on_livechange_time,None) #15 minutes
+ elif(opt == 'random wallbase'):
+ print("Sending notification 2!")
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall','Slidewall will set every 15 minutes a random wallpaper from wallbase.cc\nIf it is the first time you run this option on this session please be patient,it will take a while!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ self.on_livechange_time(None)
+ self.timer_id = GObject.timeout_add_seconds(900,self.on_livechange_time,None) #15 minutes
+ else:
+ print("Sending notification 3!")
+ #send notification
+ if(self.ui.check_notify.get_active()):
+ self.notify_engine.wall_notify('Slidewall','Slidewall will will update your clock every minute!',self.config_engine.slidewall_data+'/media/slidewall.png')
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ self.on_livechange_time(None)
+ #call sync
+ import time
+ sync = 60 - int(time.strftime("%S"))
+ print 'Window::on_bt_apply_clicked()::going live in ' + str(sync) + ' seconds'
+ self.timer_id = GObject.timeout_add_seconds(sync,self.sync_clock,None) #remaining seconds till the next minute
+
+
+ def sync_clock(self,user_data = None):
+ '''When you run a wallclock for the first time you need to make a sync.For example you start a wall clock
+ at 12:15 AM but the problem is you didn't start at 12:15:00 maybe you start at 12:15:30 or something else.So it will be
+ a bad thing to update the clock at 12:16:30.That's why you make this sync so that the next time it update exactly at
+ XX:XX:00 every time.'''
+ if('timer_id' in vars(self) or 'timer_id' in globals()):
+ GObject.source_remove(self.timer_id)
+ self.timer_id = 1
+ print('Window::sync_clock()::called')
+ self.on_livechange_time(None)
+ self.timer_id = GObject.timeout_add_seconds(60,self.on_livechange_time,None) #1 minute
+ #don't get back here
+ return False
+ def set_autostart(self):
+ '''Enable Slidewall to start when Ubuntu starts.Just copy slidewall.desktop
+ in /home/user/.config/autostart and Slidewall will autostart.'''
+ desktop = '[Desktop Entry]\nName=Slidewall\nComment=Slidewall application\nCategories=GNOME;Utility;\nExec=/opt/extras.ubuntu.com/slidewall/bin/slidewall\nIcon=/opt/extras.ubuntu.com/slidewall/share/slidewall/media/slidewall.svg\nTerminal=false\nType=Application\n'
+ autostart = open(self.config_engine.home_dir + '/.config/autostart/slidewall.desktop','w')
+ autostart.write(desktop)
+ autostart.close()
+
+ def on_bt_add_clock_clicked(self, widget, data = None):
+ '''Import wallclock's '''
+ self.wallclock_engine.import_wallclock_dialog(parent = self)
+
+ def on_bt_del_clock_clicked(self,widget, data = None ):
+ '''Remove selected bins from LiveMode but except live eart,new wallbase, random wallbase, clock radarblue and
+ clock goldflame'''
+ ret = self.live_engine.remove_bin(widget,data)
+ if(ret == True):
+ self.notify_engine.wall_notify('Slidewall','Slidwall would not work as expected without this widget!',self.config_engine.slidewall_data+'/media/slidewall.png')
\ No newline at end of file
=== added file 'slidewall_lib/__init__.py'
--- slidewall_lib/__init__.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/__init__.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,23 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+'''facade - makes slidewall_lib package easy to refactor
+
+while keeping its api constant'''
+from . helpers import set_up_logging
+from . Window import Window
+from . slidewallconfig import get_version
+
=== added file 'slidewall_lib/helpers.py'
--- slidewall_lib/helpers.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/helpers.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,111 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+"""Helpers for an Ubuntu application."""
+import logging
+import os
+
+from . slidewallconfig import get_data_file
+from . Builder import Builder
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+def get_builder(builder_file_name):
+ """Return a fully-instantiated Gtk.Builder instance from specified ui
+ file
+
+ :param builder_file_name: The name of the builder file, without extension.
+ Assumed to be in the 'ui' directory under the data path.
+ """
+ # Look for the ui file that describes the user interface.
+ ui_filename = get_data_file('ui', '%s.ui' % (builder_file_name,))
+ if not os.path.exists(ui_filename):
+ ui_filename = None
+
+ builder = Builder()
+ builder.set_translation_domain('slidewall')
+ builder.add_from_file(ui_filename)
+ return builder
+
+
+# Owais Lone : To get quick access to icons and stuff.
+def get_media_file(media_file_name):
+ media_filename = get_data_file('media', '%s' % (media_file_name,))
+ if not os.path.exists(media_filename):
+ media_filename = None
+
+ return "file:///"+media_filename
+
+class NullHandler(logging.Handler):
+ def emit(self, record):
+ pass
+
+def set_up_logging(opts):
+ # add a handler to prevent basicConfig
+ root = logging.getLogger()
+ null_handler = NullHandler()
+ root.addHandler(null_handler)
+
+ formatter = logging.Formatter("%(levelname)s:%(name)s: %(funcName)s() '%(message)s'")
+
+ logger = logging.getLogger('slidewall')
+ logger_sh = logging.StreamHandler()
+ logger_sh.setFormatter(formatter)
+ logger.addHandler(logger_sh)
+
+ lib_logger = logging.getLogger('slidewall_lib')
+ lib_logger_sh = logging.StreamHandler()
+ lib_logger_sh.setFormatter(formatter)
+ lib_logger.addHandler(lib_logger_sh)
+
+ # Set the logging level to show debug messages.
+ if opts.verbose:
+ logger.setLevel(logging.DEBUG)
+ logger.debug('logging enabled')
+ if opts.verbose > 1:
+ lib_logger.setLevel(logging.DEBUG)
+
+def get_help_uri(page=None):
+ # help_uri from source tree - default language
+ here = os.path.dirname(__file__)
+ help_uri = os.path.abspath(os.path.join(here, '..', 'help', 'C'))
+
+ if not os.path.exists(help_uri):
+ # installed so use gnome help tree - user's language
+ help_uri = 'slidewall'
+
+ # unspecified page is the index.page
+ if page is not None:
+ help_uri = '%s#%s' % (help_uri, page)
+
+ return help_uri
+
+def show_uri(parent, link):
+ from gi.repository import Gtk # pylint: disable=E0611
+ screen = parent.get_screen()
+ Gtk.show_uri(screen, link, Gtk.get_current_event_time())
+
+def alias(alternative_function_name):
+ '''see http://www.drdobbs.com/web-development/184406073#l9'''
+ def decorator(function):
+ '''attach alternative_function_name(s) to function'''
+ if not hasattr(function, 'aliases'):
+ function.aliases = []
+ function.aliases.append(alternative_function_name)
+ return function
+ return decorator
=== added file 'slidewall_lib/slidewallconfig.py'
--- slidewall_lib/slidewallconfig.py 1970-01-01 00:00:00 +0000
+++ slidewall_lib/slidewallconfig.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,74 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+# THIS IS Slidewall CONFIGURATION FILE
+# YOU CAN PUT THERE SOME GLOBAL VALUE
+# Do not touch unless you know what you're doing.
+# you're warned :)
+
+__all__ = [
+ 'project_path_not_found',
+ 'get_data_file',
+ 'get_data_path',
+ ]
+
+# Where your project will look for your data (for instance, images and ui
+# files). By default, this is ../data, relative your trunk layout
+__slidewall_data_directory__ = '../data/'
+__license__ = 'GPL-3'
+__version__ = '12.07'
+
+import os
+
+import gettext
+from gettext import gettext as _
+gettext.textdomain('slidewall')
+
+class project_path_not_found(Exception):
+ """Raised when we can't find the project directory."""
+
+
+def get_data_file(*path_segments):
+ """Get the full path to a data file.
+
+ Returns the path to a file underneath the data directory (as defined by
+ `get_data_path`). Equivalent to os.path.join(get_data_path(),
+ *path_segments).
+ """
+ return os.path.join(get_data_path(), *path_segments)
+
+
+def get_data_path():
+ """Retrieve slidewall data path
+
+ This path is by default <slidewall_lib_path>/../data/ in trunk
+ and /usr/share/slidewall in an installed version but this path
+ is specified at installation time.
+ """
+
+ # Get pathname absolute or relative.
+ path = os.path.join(
+ os.path.dirname(__file__), __slidewall_data_directory__)
+
+ abs_data_path = os.path.abspath(path)
+ if not os.path.exists(abs_data_path):
+ raise project_path_not_found
+
+ return abs_data_path
+
+
+def get_version():
+ return __version__
=== added directory 'tests'
=== added file 'tests/test_example.py'
--- tests/test_example.py 1970-01-01 00:00:00 +0000
+++ tests/test_example.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import sys
+import os.path
+import unittest
+sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), "..")))
+
+from slidewall import AboutSlidewallDialog
+
+class TestExample(unittest.TestCase):
+ def setUp(self):
+ self.AboutSlidewallDialog_members = [
+ 'AboutDialog', 'AboutSlidewallDialog', 'gettext', 'logger', 'logging']
+
+ def test_AboutSlidewallDialog_members(self):
+ all_members = dir(AboutSlidewallDialog)
+ public_members = [x for x in all_members if not x.startswith('_')]
+ public_members.sort()
+ self.assertEqual(self.AboutSlidewallDialog_members, public_members)
+
+if __name__ == '__main__':
+ unittest.main()
=== added file 'tests/test_lint.py'
--- tests/test_lint.py 1970-01-01 00:00:00 +0000
+++ tests/test_lint.py 2013-05-09 22:05:30 +0000
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2012 fioan89@xxxxxxxxx <fioan89@xxxxxxxxx>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>.
+### END LICENSE
+
+import unittest
+import subprocess
+
+class TestPylint(unittest.TestCase):
+ def test_project_errors_only(self):
+ '''run pylint in error only mode
+
+ your code may well work even with pylint errors
+ but have some unusual code'''
+ return_code = subprocess.call(["pylint", '-E', 'slidewall'])
+ # not needed because nosetests displays pylint console output
+ #self.assertEqual(return_code, 0)
+
+ # un-comment the following for loads of diagnostics
+ #~ def test_project_full_report(self):
+ #~ '''Only for the brave
+#~
+ #~ you will have to make judgement calls about your code standards
+ #~ that differ from the norm'''
+ #~ return_code = subprocess.call(["pylint", 'slidewall'])
+
+if __name__ == '__main__':
+ 'you will get better results with nosetests'
+ unittest.main()