--- /dev/null
+ 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>.
+
--- /dev/null
+Welcome to the MovieSchedule source code.
+
+I am using NokiaQtSDK to develop this Qt 4.6 based application.
+Unfortunatly the released SDK is not yet ready to support all
+features I would like to have. Development to the N900 phone is not
+yet finished (it is much better on the master branch of Qt Creator).
+Even with the new Qt Mobility libraries some features are missing which
+I wanted to use to integrate MovieSchedule into the phone's software
+(like adding entries to the calendar).
+
+So I decided to develop in a quite complex environment. The file
+"movie-schedule.pro.user (Example)" is a copy of the .pro.user file that
+I use: It defines several build targets for compiling the software to the
+normal Desktop (Ubuntu in my case), the MADDE environment, MAEMO SDK and
+Qt Simulator. Only the MAEMO SDK targets for x86 and ARMEL support all
+features of the software and have a nice looking GUI. I use the Desktop
+target for debugging the main application and the other targets for my
+technical interest only. There is also a target "LUpdate" which I use to
+update the internationalization files (so far German only).
+
+To use that .pro.user file you must replace some absolut pathes like
+"/scratchbox/users/jbecher/home/jbecher/Movies/" with your own directory.
+The source code must be placed in "movie-schedule" within that directory.
+
+If you wonder why I decided to have "movie-schedule" in the scratchbox: I
+need this to build the software within the MAEMO SDK.
+
+To deploy a debian package of the software goto the movie-schedule directory
+and enter "dpkg-buildpackage -rfakeroot".
+
+If you plan to improve the software or to cross compile it for another
+phone (e.g. Symbian) please contact me (Jochen Becher <j.becher@ovi.com>).
+I would like to coordinate those efforts.
+
+Regards, Jochen "gilead" Becher
+
--- /dev/null
+[Desktop Entry]
+Encoding=UTF-8
+Version=0.1.0
+Type=Application
+Name=MovieSchedule
+Exec=/usr/bin/movie-schedule
+Icon=movie-schedule
+X-Window-Icon=movie-schedule
+X-HildonDesk-ShowInToolbar=true
+X-Osso-Type=application/x-executable
+Terminal=false
+Name[de_DE]=movie-schedule.desktop
--- /dev/null
+movie-schedule (0.2.0) unstable; urgency=low
+
+ * Fixed trimming of phone numbers before calling cinema (Closes: #6110)
+ * Added work-around for trashed locations (Closes: #6109)
+
+ -- Jochen Becher <j.becher@ovi.com> Thu, 08 Aug 2010 17:15:00 +0000
+
+movie-schedule (0.1.0) unstable; urgency=low
+
+ * Initial release (Closes: #0000)
+
+ -- Jochen Becher <j.becher@ovi.com> Mon, 31 May 2010 23:50:29 +0000
+
--- /dev/null
+Source: movie-schedule
+Section: user/network
+Priority: optional
+Maintainer: Jochen Becher <j.becher@ovi.com>
+Build-Depends: debhelper (>= 5), libqt4-core, libqt4-gui, icd2-dev, maemo-optify, liblocation-dev, libgconf2-dev, libqt4-dev, calendar-backend-dev
+Standards-Version: 3.7.3
+
+Package: movie-schedule
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Find movies at cinemas near your town.
+ MovieSchedule presents movies found in Googles movie-service.
+ Search through the movies shown in a cinema within the next
+ days or find your preferred time to watch the latest block buster.
+ Don't miss a movie by addding a calendar entry automatically or
+ google for the cinema's or movie's web page.
+XSBC-Bugtracker: https://bugs.maemo.org/enter_bug.cgi?product=movie-schedule
+XSBC-Maemo-Display-Name: MovieSchedule
+XB-Maemo-Icon-26:
+ iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAL
+ EwAACxMBAJqcGAAAAAd0SU1FB9oHGA0TFCsRMDUAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRo
+ IEdJTVBXgQ4XAAAJu0lEQVRo3u1Za0yUVxp+zjfOTZiBKQw3GZgdgQ5t0ai7ilVpKNmabrxUrElb
+ S7sxaXcb2dim+qM/TEy6TVa7TTZhE1kxKSV03VK1F1tEYKBEWqTcVAotODPM4DDKTZj79813OfsD
+ mUqVipeATXx+zbxn3u+c53vPex3gIR7iniB7EA+lUi1WvPnmW7ri4t1LCgoK9oTDXJLdbv/hVr9d
+ 9ACdO/7ll/9sVCgUz0VFRWWq1YvXP/XUUykpKSmQyRZV19XV/+9BJPDYgQMH1iYlJf29sLCQlJdX
+ qFyuyzGiyMPptGN83EPV6hii16f8abYHzBsBk8kUtWvXrqiGhqbfabXaHfHx8c9t3rxp6ZYtmwCA
+ ShKI2ZyN9vbvQQihPM+TI0f+Q3bv3ovExDQAWAGga74JJJSWlj5hMBg2aLXaDQwjW8VxQizLhhAM
+ BnD2bBNdtWo1ARjCcTxycn5PGaaSjI6OkHA4HBodHeuyWOrsExPXnGvWrBtqbf12Xixg2rp1+7bU
+ 1NRCrVabuXLlKvWyZTnRDCMDx/H48cefqMVSRwRBQCDgJxbLN8jN3QCe52G19pLY2Phvv/mm4d3k
+ 5JTzPp8vWFy8iwXAz7YZuZeTpqamRb3wwktqnU6TwjDM3uXLl2/T6xOiP/30BFg2iGAwSGNiYsg7
+ 7+xHMMhBEETYbJdQUvJPBAIBjud5v1wuD6xdm++5eLFz35dfnjxzp2e4GwukvPbaX5fHxOiWB4O+
+ jYLA57z00s44ozEdokghiqBVVVXkyhU3KKVkfHwcDQ1NMJtz4HQOIBQKWXlePDk8PNw+MjLSNTIy
+ YrVYLHf9EudKQL9///69ubm5z23YsEF37lxr1Fdffb0YoBgfH0Nz87c0OvoREggEEA6LJC9vI9ra
+ 3gXDMPB6vfjiixOldXW1nXl5T39dV1fNnj799bX7dV9vIlBUVKRetWplXE9Pv87jmXxDo9G+kZWV
+ hbff3gOGkYFlOZhMGQgE/PD7fZTneXLsWCUxm1dCFCWJEAQJYYYA5vPm5uaj4XDY2t7eDgAoK/v3
+ fXe4GQQOHz4cl52dXaXRaJ7WanW4cOECeD6Mvr4enD5dixUrVoPjOCgUWpqebiIWSw0RRWnM7/cN
+ NDXVfyEIou/kyaoL33//XdN8hecZBDiOk2u1MasffTQbarUWNTXVkCQJPM/T2tpaYjBkgWFk6Oz8
+ jlAqO+5w2It1ung6OjrG7t37N+9CZMIZBMrKjvpMJnNbTExivigySE42oLu7yy8IAudyuYYSEpZ8
+ Xln54U99fb3HpnWcTteCpvIZBHp6fgg4HJfPXbvmy09MTDojk8kvDg4OnrBarS4AQx0dHQ9c4XdT
+ Htiz560sg8FQ5HYPe8NhPiCXy0WGkZG0tCRCCEAIgdfrx+ioB4AESZKwZEkS1GrFVHkrk8Fud0EU
+ RQAAw8hgNCZPbUYIPB4/xsYmAACiKMFgSIZKJY/o2myXIUlS5Ht6egoACkII+vr6hsvLy0/5/X5+
+ VgKdnZ1rV6xY0ehwDCpbWtogly8Cw8jw5JN/QFJS4rSvoKbGAp7nIYoUS5YkYv36tZFn2O0OtLZ2
+ RHTXrVuNxMQEAADLcjhzpgE8H4YoSkhNTcG6dWsiulbrANraOiO669evQUKCHgBgsVg6X3nllXy3
+ 2+2dNYxOTnooy4Y5rVartNt/QiAQAKUAx/mxdes2MAyBUqlEKOTD+fNdkMlkaGvjYDSmIzExAaIo
+ ITY2FjZbL4LBECgFBCGIzZu3gBAGSqUSfv8Euru7IZMxaG8Pw2RKR1xcPCRJgk4Xg0uXesCyLCgF
+ RJHFpk2bIZPJwPNCWBAEeuN5mV8SCIdFcJwIQuRISEiGw+HA4KATp09XY2zsGlhWgNcbQl7e07Ba
+ rXA6nXC73Sgv/xCiyIBlBRAih16fFNGtrq7G2NgkWFaAz8de1+2H0+nE0NAQyss/AqUysKwAhlFC
+ r0+cse/4+JQuz0uEUkp+NZE1NFi4wUHnZYBE2+023aVLlzSiKBKO4/D++/+A2WyGJFEolUr4fH5Y
+ rVYwDAOr1QalUg21WgVCCAYGBtDf3w9JksBxHD744BAyMzMhSRQqlQqTk16MjdnAMAxsNhsUCgWU
+ SiUIIbDbbTfosigp+VcwIyNLcDhs/YFAMDznYs5uH/jv6OjIC9Osw+EwBEGIrCuVKshkU0aklF43
+ O404oEKhBCHTlp0q5n5uG1VgmNl0F0GhUIAQQJIkpKWl9QLkcnq68S+iyDvnFJ68Xq9WEIRzdOEh
+ UUqp1+vzPvFETu4vz8nMToGhdPqVLHCopxQgBJSQm4/L/BZGJyRy0elvk8Cv4SGBaYRCIbhcLgQC
+ gRnyYDAIl8uF8fHxGXKe53H16lW43W7ci6vdFwLNzc3Ytm0bDAYDSkpKIvKWlhZs2bIFBoMBBQUF
+ EbnD4cDrr7+OjIwMZGZmwmaz3W3p9qthVMPzfMvtYtzBgwfpde+iAGhlZSWllNKSkpIZcqPRSCml
+ tLm5mSqVyog8NjaWdnV13TaW+nw+T07OHYXR2+PgwYO4ePEibmzKn3nmGVRUVKClpQUdHR3IyMgA
+ AOTl5aGjowOFhYUoKyvD7t27AQBqtRpLly5dmCv04osvorKyElFRUQCA5ORk+P1+9PT04OOPP0ZG
+ Rgbk8qlSuaCgAAcOHEBTUxOKiorg9/unZouPPQaNRjOn/W7lKvc02EpLS4vcdQAoLCxEcXExqqqq
+ Ig7c398PpVKJtrY2FBcXw2w2Y2JiIqLz/PPP39+pxN2gsbERAFBfX4/Dhw9HLNLX1wdRFGEwGMCy
+ LDZu3AgAuHr1Kvr7+wEA27dvn/Pbv5UFmDsx12yora0FAKSnpyM/Pz8iP3XqFABgdHQUpaWlEfmJ
+ EyemB77Q6/ULmwe6u7vBsiwA4L333puxdvz4cQDAvn37IJP9/F/KsWNTM4EdO3bc0V63yhf3TGD6
+ vhuNRphMpoh8eHgYTudU5btz584bGqYwent7AQDPPvssrly5goaGhkgfPO8W+OyzzwAAy5Ytw+LF
+ iyPyioqK6wPgVOh0uoi8vr4+8vnIkSN49dVXwXFcpDeYVyfu7u6G1WoFAGRmZkKlUkXWjh49CgBI
+ SkqCQqGIyIeGhn7efNEifPLJJzMIznJ5Zq1GZ4XHc/tM7Ha7aWtr680diCTRmpoaOjk5edOaKIr0
+ 0KFD9Pz583fU1Xi9Xk929uO5d0DAM6dSYr7g8Xg9ZvPjcy8lCGFACMEDAnq9ghXm7ANnz54lGo0m
+ Ojo6esGJ8DxP9Hp9g83WP/c/+RobG31xcY/8MS4uQcEwC0mAIBQKkqyszDEAIh7iIe4v/g9Ndly/
+ gHHgugAAAABJRU5ErkJggg==
--- /dev/null
+This package was debianized by Jochen Becher <j.becher@ovi.com> on
+Mon, 31 May 2010 23:50:29 +0000.
+
+Copyright: (C) 2010 Jochen Becher
+
+License:
+
+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/>.
+
--- /dev/null
+#!/bin/sh -e
+
+gtk-update-icon-cache -f /usr/share/icons/hicolor
+
+exit 0
+
--- /dev/null
+#!/usr/bin/make -f
+APPNAME := movie-schedule
+builddir:
+ mkdir -p builddir
+
+builddir/Makefile: builddir
+ cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro CONFIG+=maemo_sdk
+
+build: build-stamp
+
+build-stamp: builddir/Makefile
+ dh_testdir
+ # Add here commands to compile the package.
+ cd builddir && $(MAKE)
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ # Add here commands to clean up after the build process.
+ rm -rf builddir
+ dh_clean
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/your_appname
+ cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installdocs
+ dh_installexamples
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ maemo-optify
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
+
--- /dev/null
+QMAKEVERSION = $$[QMAKE_VERSION]
+ISQT4 = $$find(QMAKEVERSION, ^[2-9])
+isEmpty( ISQT4 ) {
+ error("Use the qmake include with Qt4.4 or greater.");
+}
+
+TEMPLATE = subdirs
+SUBDIRS = src
--- /dev/null
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">2</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value key="EditorConfiguration.Codec" type="QByteArray">System</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Maemo</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.MaemoDeviceTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">1</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList">
+ <value type="QString">CONFIG+=mobility</value>
+ </valuelist>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.2" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoPackageCreationStep</value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.LocalFiles" type="QVariantList"/>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.Modified" type="bool">true</value>
+ <value key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteExe" type="QString">/usr/local/bin/movie-schedule</value>
+ <valuelist key="Qt4ProjectManager.BuildStep.MaemoPackage.RemoteFiles" type="QVariantList"/>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">3</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-arm-debug-madde</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">3</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">9</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">sb-conf</value>
+ <value type="QString">select</value>
+ <value type="QString">FREMANTLE_ARMEL</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Select Target</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-arm-debug-sdk</value>
+ <value type="QString">qmake</value>
+ <value type="QString">../movie-schedule/movie-schedule.pro</value>
+ <value type="QString">-r</value>
+ <value type="QString">-spec</value>
+ <value type="QString">linux-g++</value>
+ <value type="QString">CONFIG+=maemo_sdk</value>
+ <value type="QString">CONFIG+=debug</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">QMake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.2" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-arm-debug-sdk</value>
+ <value type="QString">make</value>
+ <value type="QString">-w</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">3</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-arm-debug-sdk</value>
+ <value type="QString">make</value>
+ <value type="QString">-w</value>
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Clean</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug (SDK)</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-arm-debug-sdk</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">3</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">9</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key=".ProFile" type="QString">src/src.pro</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">N900</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoRunConfiguration</value>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.Arguments" type="QVariantList"/>
+ <valuemap key="Qt4ProjectManager.MaemoRunConfiguration.DebuggingHelpersLastDeployed" type="QVariantMap"/>
+ <value key="Qt4ProjectManager.MaemoRunConfiguration.DeviceId" type="qulonglong">1</value>
+ <valuemap key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployed" type="QVariantMap"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.1" type="QVariantMap">
+ <value key=".ProFile" type="QString">src/src.pro</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">N900 Emulator</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MaemoRunConfiguration</value>
+ <valuelist key="Qt4ProjectManager.MaemoRunConfiguration.Arguments" type="QVariantList"/>
+ <valuemap key="Qt4ProjectManager.MaemoRunConfiguration.DebuggingHelpersLastDeployed" type="QVariantMap"/>
+ <value key="Qt4ProjectManager.MaemoRunConfiguration.DeviceId" type="qulonglong">9</value>
+ <valuemap key="Qt4ProjectManager.MaemoRunConfiguration.LastDeployed" type="QVariantMap"/>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">2</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.1</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Qt Simulator</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.QtSimulatorTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList">
+ <value type="QString">CONFIG+=mobility</value>
+ </valuelist>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-simulator</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Release</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-build-simulator</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">src</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">src/src.pro</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.2</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-desktop</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">8</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">sb-conf</value>
+ <value type="QString">select</value>
+ <value type="QString">FREMANTLE_X86</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Select Target</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">mkdir</value>
+ <value type="QString">-p</value>
+ <value type="QString">Movies/movie-schedule-x86-debug-sdk</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Create Builddir</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.2" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-x86-debug-sdk</value>
+ <value type="QString">qmake</value>
+ <value type="QString">../movie-schedule/movie-schedule.pro</value>
+ <value type="QString">-r</value>
+ <value type="QString">-spec</value>
+ <value type="QString">linux-g++</value>
+ <value type="QString">CONFIG+=maemo_sdk</value>
+ <value type="QString">CONFIG+=debug</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">QMake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.3" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-x86-debug-sdk</value>
+ <value type="QString">make</value>
+ <value type="QString">-w</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">4</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">-d</value>
+ <value type="QString">Movies/movie-schedule-x86-debug-sdk</value>
+ <value type="QString">make</value>
+ <value type="QString">-w</value>
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">/scratchbox/login</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Clean</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug (SDK)</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-sdk</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">8</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.2" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <valuelist key="ProjectExplorer.ProcessStep.Arguments" type="QVariantList">
+ <value type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule/movie-schedule.pro</value>
+ </valuelist>
+ <value key="ProjectExplorer.ProcessStep.Command" type="QString">lupdate</value>
+ <value key="ProjectExplorer.ProcessStep.Enabled" type="bool">true</value>
+ <value key="ProjectExplorer.ProcessStep.WorkingDirectory" type="QString">$BUILDDIR</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">LUpdate</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.ProcessStep</value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">0</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">LUpdate</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-lupdate</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">8</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">3</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">src</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">src/src.pro</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">3</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">4</value>
+ </data>
+</qtcreator>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "actioncontroller.h"
+
+#include "data/cinemaschedule.h"
+#include "data/scheduleentry.h"
+#include "data/cinema.h"
+#include "data/movie.h"
+#include "ui/uiutils.h"
+#include "utils/calendar.h"
+#include "utils/timeutils.h"
+#include "utils/assertedlocker.h"
+
+#include <QtDBus>
+#include <QUrl>
+#include <QDesktopServices>
+#include <iostream>
+
+ActionController::ActionController(const CinemaSchedule *cinema_schedule) :
+ QObject(0),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+void ActionController::AddToCalendar(ScheduleEntryKey schedule_entry_key)
+{
+#ifdef MAEMO_SDK
+ ScheduleEntry schedule_entry;
+ Movie movie;
+ Cinema cinema;
+ {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ schedule_entry = _cinema_schedule->FindScheduleEntry(schedule_entry_key);
+ if (schedule_entry.IsValid()) {
+ movie = *schedule_entry.GetMovie();
+ cinema = *schedule_entry.GetCinema();
+ }
+ }
+ if (schedule_entry.IsValid()) {
+ Calendar calendar(this);
+ QDateTime start_time;
+ start_time.setDate(schedule_entry.GetDate());
+ start_time.setTime(schedule_entry.GetStartTime());
+ int minutes = movie.GetDuration().hour() * 60
+ + movie.GetDuration().minute();
+ minutes = ((minutes + 14) / 15) * 15;
+ QDateTime end_time = start_time.addSecs(minutes * 60);
+ QString location = cinema.GetName();
+ QString description;
+ if (!cinema.GetAddress().isEmpty()) {
+ if (!location.isEmpty()) {
+ location += ", ";
+ }
+ location += cinema.GetAddress();
+ }
+ if (!cinema.GetTelephone().isEmpty()) {
+ if (!description.isEmpty()) {
+ description += "\n";
+ }
+ description += cinema.GetTelephone();
+ }
+ if (!calendar.AddEvent(movie.GetName(), start_time, end_time,
+ location, description)) {
+ ShowError(tr("Adding calendar event failed."));
+ return;
+ }
+ UiUtils::ShowInformation(
+ tr("%1 (%2 %3) added to your calendar.")
+ .arg(movie.GetName())
+ .arg(TimeUtils::ToDateString(schedule_entry.GetDate()))
+ .arg(TimeUtils::ToTimeString(schedule_entry.GetStartTime())));
+ } else {
+ ShowError(tr("Adding calendar event failed."));
+ }
+#else
+ Q_UNUSED(schedule_entry_key);
+ ShowError(tr("Adding calendar event failed."));
+#endif
+}
+
+void ActionController::CallTheaterByPhone(CinemaKey cinema_key)
+{
+ Cinema cinema;
+ {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Cinema *cinema_p = _cinema_schedule->FindCinema(cinema_key);
+ if (cinema_p != 0) {
+ cinema = *cinema_p;
+ }
+ }
+ if (cinema.IsValid()) {
+ if (!cinema.GetTelephone().isEmpty()) {
+ if (!QDBusConnection::systemBus().isConnected()) {
+ ShowError(tr("Unable to call theater by phone: communication bus not available."));
+ return;
+ }
+ QDBusInterface iface("com.nokia.csd.Call", "/com/nokia/csd/call", "com.nokia.csd.Call", QDBusConnection::systemBus());
+ if (!iface.isValid()) {
+ ShowError(tr("Unable to call theater by phone: phone service not available."));
+ return;
+ }
+ QString phone_number = TrimPhoneNumber(cinema.GetTelephone());
+ QDBusReply<QDBusObjectPath> reply = iface.call("CreateWith", phone_number, 0);
+ if (!reply.isValid()) {
+ std::cout << qPrintable(reply.error().message()) << ": <" << qPrintable(phone_number) << ">" << std::endl;
+ ShowError(tr("Unable to call theater by phone: call failed."));
+ return;
+ }
+ }
+ }
+}
+
+void ActionController::FindRouteToTheater(CinemaKey cinema_key)
+{
+ Cinema cinema;
+ {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Cinema *cinema_p = _cinema_schedule->FindCinema(cinema_key);
+ if (cinema_p != 0) {
+ cinema = *cinema_p;
+ }
+ }
+ if (cinema.IsValid()) {
+ // TODO implement find route to theater
+ }
+}
+
+void ActionController::SearchTheaterInWeb(CinemaKey cinema_key)
+{
+ QString key;
+ {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Cinema *cinema = _cinema_schedule->FindCinema(cinema_key);
+ if (cinema != 0) {
+ key = cinema->GetName() + " " + cinema->GetAddress();
+ }
+ }
+ if (!key.isEmpty()) {
+ SearchInWeb(key);
+ }
+}
+
+void ActionController::SearchMovieInWeb(MovieKey movie_key)
+{
+ QString key;
+ {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Movie *movie = _cinema_schedule->FindMovie(movie_key);
+ if (movie != 0) {
+ key = movie->GetName();
+ }
+ }
+ if (!key.isEmpty()) {
+ SearchInWeb(key);
+ }
+}
+
+void ActionController::ContactAuthor()
+{
+ QUrl url("mailto::Jochen Becher <j.becher@ovi.com>", QUrl::TolerantMode);
+ url.addQueryItem("subject", "Application 'MovieSchedule' for Nokia N900");
+ QDesktopServices::openUrl(url);
+}
+
+QString ActionController::TrimPhoneNumber(const QString &phone_number)
+{
+ QString trimmed;
+ bool plus_is_valid = true;
+ foreach (QChar ch, phone_number) {
+ switch (ch.toAscii()) {
+ case ',':
+ case '.':
+ case '(':
+ case ')':
+ case '-':
+ case ' ':
+ case '\t':
+ case '/':
+ // trim character
+ break;
+ case 'p':
+ case 'w':
+ case 'x':
+ trimmed += ch.toUpper();
+ break;
+ case '+':
+ if (plus_is_valid) {
+ trimmed += ch;
+ }
+ break;
+ default:
+ trimmed += ch;
+ }
+ // TODO plus_is_valid stays true as long as we are parsing a number suppression prefix (e.g. *31#)
+ plus_is_valid = false;
+ }
+ return trimmed;
+}
+
+void ActionController::SearchInWeb(const QString &key)
+{
+ QUrl url("http://www.google.com/search");
+ url.addQueryItem("q", key);
+ if (!QDesktopServices::openUrl(url)) {
+ ShowError(tr("Unable to search in web: browser service not available."));
+ return;
+ }
+}
+
+void ActionController::ShowError(const QString &msg)
+{
+ UiUtils::ShowError(msg);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ACTIONCONTROLLER_H
+#define ACTIONCONTROLLER_H
+
+#include "data/cinemakey.h"
+#include "data/moviekey.h"
+#include "data/scheduleentrykey.h"
+
+#include <QObject>
+
+class CinemaSchedule;
+
+class ActionController : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ActionController(const CinemaSchedule *cinema_schedule);
+
+public:
+ Q_SLOT void AddToCalendar(ScheduleEntryKey);
+ Q_SLOT void CallTheaterByPhone(CinemaKey);
+ Q_SLOT void FindRouteToTheater(CinemaKey);
+ Q_SLOT void SearchTheaterInWeb(CinemaKey);
+ Q_SLOT void SearchMovieInWeb(MovieKey);
+ Q_SLOT void ContactAuthor();
+
+private:
+ QString TrimPhoneNumber(const QString &phone_number);
+ void SearchInWeb(const QString &key);
+ void ShowError(const QString &);
+
+private:
+ const CinemaSchedule *_cinema_schedule;
+};
+
+#endif // ACTIONCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "itemmodelsortclient.h"
+
+#include "itemmodelsortproxy.h"
+#include "itemmodelsortcontroller.h"
+
+#include <iostream>
+
+ItemModelSortClient::ItemModelSortClient(ItemModelSortController *controller, QObject *parent)
+ : QObject(parent),
+ _proxy(new ItemModelSortProxy(controller)),
+ _model(0),
+ _task_id(0),
+ _intermediate(false)
+{
+ connect(this, SIGNAL(Sort(QAbstractItemModel*)), _proxy, SLOT(Sort(QAbstractItemModel*)));
+ connect(_proxy, SIGNAL(SortFinished(QAbstractItemModel*)), this, SLOT(SortFinished(QAbstractItemModel*)));
+ _proxy->moveToThread(controller->thread());
+}
+
+void ItemModelSortClient::Sort(QAbstractItemModel *model, int task_id, bool intermediate)
+{
+ _model = model;
+ _task_id = task_id;
+ _intermediate = intermediate;
+ //std::cout << "Start sorting model " << model << " with intermediate = " << intermediate << std::endl;
+ emit Sort(model);
+}
+
+void ItemModelSortClient::SortFinished(QAbstractItemModel *model)
+{
+ //std::cout << "Finished sorting model " << model << " with intermediate = " << _intermediate << std::endl;
+ emit SortFinished(model, _task_id, _intermediate);
+ deleteLater();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ITEMMODELSORTCLIENT_H
+#define ITEMMODELSORTCLIENT_H
+
+#include <QObject>
+
+class ItemModelSortController;
+class QAbstractItemModel;
+class ItemModelSortProxy;
+
+class ItemModelSortClient : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ItemModelSortClient(ItemModelSortController *, QObject *parent = 0);
+
+public:
+ void Sort(QAbstractItemModel *model, int task_id, bool intermediate);
+
+public:
+ Q_SIGNAL void SortFinished(QAbstractItemModel *model, int task_id, bool intermediate);
+
+private:
+ Q_SLOT void SortFinished(QAbstractItemModel *model);
+
+private:
+ Q_SIGNAL void Sort(QAbstractItemModel *);
+
+private:
+ ItemModelSortProxy *_proxy;
+ QAbstractItemModel *_model;
+ int _task_id;
+ bool _intermediate;
+};
+
+#endif // ITEMMODELSORTCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "itemmodelsortcontroller.h"
+
+#include "data/cinemaschedule.h"
+#include "utils/assertedlocker.h"
+
+#include <QAbstractItemModel>
+#include <QThread>
+
+ItemModelSortController::ItemModelSortController(CinemaSchedule *cinema_schedule)
+ : _cinema_schedule(cinema_schedule)
+{
+}
+
+void ItemModelSortController::Sort(QAbstractItemModel *model)
+{
+ AssertedReadLocker(_cinema_schedule->GetLock());
+ model->sort(0);
+ //sleep(2);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ITEMMODELSORTCONTROLLER_H
+#define ITEMMODELSORTCONTROLLER_H
+
+#include <QObject>
+
+class CinemaSchedule;
+class QAbstractItemModel;
+
+class ItemModelSortController : public QObject
+{
+ Q_OBJECT
+public:
+ ItemModelSortController(CinemaSchedule *cinema_schedule);
+
+public:
+ void Sort(QAbstractItemModel *model);
+
+private:
+ CinemaSchedule *_cinema_schedule;
+};
+
+#endif // ITEMMODELSORTCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "itemmodelsortproxy.h"
+
+#include "itemmodelsortcontroller.h"
+
+ItemModelSortProxy::ItemModelSortProxy(ItemModelSortController *controller)
+ : _controller(controller)
+{
+}
+
+void ItemModelSortProxy::Sort(QAbstractItemModel *model)
+{
+ _controller->Sort(model);
+ emit SortFinished(model);
+ deleteLater();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ITEMMODELSORTPROXY_H
+#define ITEMMODELSORTPROXY_H
+
+#include <QObject>
+
+class ItemModelSortController;
+class QAbstractItemModel;
+
+class ItemModelSortProxy : public QObject
+{
+ Q_OBJECT
+public:
+ ItemModelSortProxy(ItemModelSortController *);
+
+public:
+ Q_SLOT void Sort(QAbstractItemModel *model);
+
+public:
+ Q_SIGNAL void SortFinished(QAbstractItemModel *model);
+
+private:
+ ItemModelSortController *_controller;
+};
+
+#endif // ITEMMODELSORTPROXY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "locationcontroller.h"
+
+#include "ui/locationdialog.h"
+#include "searchclients/gpsclient.h"
+#include "data/settings.h"
+#include "ui/mainwindow.h"
+
+static const char *MSG_LOCATION_NOT_FOUND = QT_TRANSLATE_NOOP("LocationController", "Unable to detect current city.");
+
+LocationController::LocationController(MainWindow *main_window, Settings *settings) :
+ QObject(0),
+ _main_window(main_window),
+ _settings(settings),
+ _active_search_task_id(GpsClient::INVALID_SEARCH_TASK_ID)
+{
+}
+
+void LocationController::OpenLocationDialog()
+{
+ LocationDialog *location_dialog = new LocationDialog(_main_window);
+ connect(location_dialog, SIGNAL(Search(Location)), this, SLOT(SearchLocationFromCityDatabase(Location)));
+ connect(location_dialog, SIGNAL(SearchPreviousLocation(Location)), this, SLOT(SearchLocation(Location)));
+ connect(location_dialog, SIGNAL(SearchGPS()), this, SLOT(SearchGPS()));
+ connect(location_dialog, SIGNAL(Cancel()), this, SLOT(CancelLocation()));
+ location_dialog->SetLocation(_settings->GetLocation());
+ location_dialog->SetPreviousLocations(_settings->GetPreviousLocations());
+ location_dialog->SetGPSEnabled(true || _settings->IsGPSEnabled());
+ location_dialog->show();
+ // location_dialog deletes itself
+}
+
+void LocationController::CancelAllGpsSearchs()
+{
+ _active_search_task_id = GpsClient::INVALID_SEARCH_TASK_ID;
+ GpsClient::CancelAllRunningSearchs();
+}
+
+void LocationController::SearchLocationFromCityDatabase(Location location)
+{
+ // TODO check city database
+ SearchLocation(location);
+}
+
+void LocationController::SearchLocation(Location location)
+{
+ location = CleanLocation(location);
+ RememberLocation(location);
+ emit Search(location);
+}
+
+void LocationController::SearchGPS()
+{
+ GpsClient *client = new GpsClient();
+ connect(client, SIGNAL(SearchStarted(int)), this, SLOT(GpsSearchStarted(int)));
+ connect(client, SIGNAL(PositionUpdate(int)), this, SLOT(GpsPositionUpdate(int)));
+ connect(client, SIGNAL(SearchForTownStarted(int)), this, SLOT(GpsSearchForTownStarted(int)));
+ connect(client, SIGNAL(TownUpdate(int,QString)), this, SLOT(GpsTownUpdate(int,QString)));
+ connect(client, SIGNAL(SearchError(int)), this, SLOT(GpsSearchError(int)));
+ connect(client, SIGNAL(SearchFinished(int,bool)), this, SLOT(GpsSearchFinished(int,bool)));
+ _active_search_task_id = client->GetSearchTaskId();
+ client->SearchLocation();
+ // gps client deletes itself
+}
+
+void LocationController::CancelLocation()
+{
+ // nothing to do
+}
+
+Location LocationController::CleanLocation(const Location &location)
+{
+ // TODO clash with city database?
+ QString name = location.GetLocationName().trimmed();
+ if (name.size() > 0) {
+ if (name[0].isLower()) {
+ name[0] = name[0].toUpper();
+ }
+ }
+ Location cleaned_location;
+ cleaned_location.SetLocationName(name);
+ return cleaned_location;
+}
+
+void LocationController::RememberLocation(const Location &location)
+{
+ if (!location.IsValid()) {
+ return;
+ }
+ Settings::Locations locations = _settings->GetPreviousLocations();
+ QMutableListIterator<Location> it(locations);
+ while (it.hasNext()) {
+ const Location &prev_location = it.next();
+ if (prev_location == location) {
+ it.remove();
+ }
+ }
+ locations.push_front(location);
+ while (locations.size() > 5) {
+ locations.pop_back();
+ }
+ _settings->SetPreviousLocations(locations);
+}
+
+void LocationController::GpsSearchStarted(int search_task_id)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+ _main_window->SetBusy(true);
+}
+
+void LocationController::GpsPositionUpdate(int search_task_id)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+}
+
+void LocationController::GpsSearchForTownStarted(int search_task_id)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+}
+
+void LocationController::GpsTownUpdate(int search_task_id, QString town)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+ Location location;
+ location.SetLocationName(town);
+ SearchLocation(location);
+}
+
+void LocationController::GpsSearchError(int search_task_id)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+ _main_window->SetError(tr(MSG_LOCATION_NOT_FOUND));
+}
+
+void LocationController::GpsSearchFinished(int search_task_id, bool success)
+{
+ if (_active_search_task_id != search_task_id) {
+ return;
+ }
+ // In case of success SearchLocation() is started which will
+ // unset busy state on its end
+ if (!success) {
+ _main_window->SetBusy(false);
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef LOCATIONCONTROLLER_H
+#define LOCATIONCONTROLLER_H
+
+#include "data/location.h"
+
+#include <QObject>
+
+class MainWindow;
+class Settings;
+
+class LocationController : public QObject
+{
+ Q_OBJECT
+public:
+ explicit LocationController(MainWindow *main_window, Settings *settings);
+
+public:
+ Q_SLOT void OpenLocationDialog();
+
+ void CancelAllGpsSearchs();
+
+public:
+ Q_SIGNAL void Search(Location location);
+
+private:
+ Q_SLOT void SearchLocationFromCityDatabase(Location location);
+ Q_SLOT void SearchLocation(Location location);
+ Q_SLOT void SearchGPS();
+ Q_SLOT void CancelLocation();
+ Location CleanLocation(const Location &location);
+ void RememberLocation(const Location &location);
+
+ Q_SLOT void GpsSearchStarted(int search_task_id);
+ Q_SLOT void GpsPositionUpdate(int search_task_id);
+ Q_SLOT void GpsSearchForTownStarted(int search_task_id);
+ Q_SLOT void GpsTownUpdate(int search_task_id, QString town);
+ Q_SLOT void GpsSearchError(int search_task_id);
+ Q_SLOT void GpsSearchFinished(int search_task_id, bool success);
+
+private:
+ MainWindow *_main_window;
+ Settings *_settings;
+ int _active_search_task_id;
+};
+
+#endif // LOCATIONCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "maincontroller.h"
+
+#include "data/settings.h"
+#include "data/cinemaschedule.h"
+#include "data/movie.h"
+#include "data/cinema.h"
+#include "control/theatercontroller.h"
+#include "control/moviecontroller.h"
+#include "control/actioncontroller.h"
+#include "control/locationcontroller.h"
+#include "control/itemmodelsortclient.h"
+#include "ui/aboutdialog.h"
+#include "ui/mainwindow.h"
+#include "ui/theatermodel.h"
+#include "ui/moviemodel.h"
+#include "ui/uiutils.h"
+#include "searchclients/theatersearchclient.h"
+#include "searchclients/moviesearchclient.h"
+#include "utils/assertedlocker.h"
+#include "utils/asynccall.h"
+#include "utils/connectivitymanager.h"
+
+#include <QSortFilterProxyModel>
+#include <iostream>
+
+static const char *MSG_NETWORK_ERROR = QT_TRANSLATE_NOOP("MainController", "Unable to access network.");
+static const char *MSG_NO_THEATERS_FOUND = QT_TRANSLATE_NOOP("MainController", "No theaters found near %1.");
+static const char *MSG_NO_MOVIES_FOUND = QT_TRANSLATE_NOOP("MainController", "No movies found near %1.");
+static const char *MSG_THEATERS_ERROR = QT_TRANSLATE_NOOP("MainController", "Error on fetching theaters.");
+static const char *MSG_MOVIES_ERROR = QT_TRANSLATE_NOOP("MainController", "Error on fetching movies.");
+
+MainController::MainController(MainWindow *main_window, Settings *settings, CinemaSchedule *cinema_schedule,
+ TheaterController *theater_controller,
+ MovieController *movie_controller,
+ LocationController *location_controller,
+ ActionController *action_controller,
+ ItemModelSortController *sort_controller,
+ QThread *search_worker)
+ : _main_window(main_window),
+ _settings(settings),
+ _cinema_schedule(cinema_schedule),
+ _theater_controller(theater_controller),
+ _movie_controller(movie_controller),
+ _location_controller(location_controller),
+ _action_controller(action_controller),
+ _sort_controller(sort_controller),
+ _search_worker(search_worker),
+ _connectivity_manager(new ConnectivityManager(this)),
+ _current_theater_search_task_id(TheaterSearchClient::INVALID_SEARCH_TASK_ID),
+ _current_movies_search_task_id(MovieSearchClient::INVALID_SEARCH_TASK_ID),
+ _theater_model(new TheaterModel(cinema_schedule, this)),
+ _movie_model(new MovieModel(cinema_schedule, this)),
+ _theater_proxy_model(new QSortFilterProxyModel(this)),
+ _movie_proxy_model(new QSortFilterProxyModel(this)),
+ _last_search_settings()
+{
+ connect(_main_window, SIGNAL(SearchTheaters()), this, SLOT(SearchTheaters()));
+ connect(_main_window, SIGNAL(SearchMovies()), this, SLOT(SearchMovies()));
+ connect(_main_window, SIGNAL(TheaterSelected(CinemaKey)), _theater_controller, SLOT(ShowTheater(CinemaKey)));
+ connect(_main_window, SIGNAL(CallTheaterByPhone(CinemaKey)), _action_controller, SLOT(CallTheaterByPhone(CinemaKey)));
+ connect(_main_window, SIGNAL(FindRouteToTheater(CinemaKey)), _action_controller, SLOT(FindRouteToTheater(CinemaKey)));
+ connect(_main_window, SIGNAL(SearchTheaterInWeb(CinemaKey)), _action_controller, SLOT(SearchTheaterInWeb(CinemaKey)));
+ connect(_main_window, SIGNAL(MovieSelected(MovieKey)), _movie_controller, SLOT(ShowMovie(MovieKey)));
+ connect(_main_window, SIGNAL(SearchMovieInWeb(MovieKey)), _action_controller, SLOT(SearchMovieInWeb(MovieKey)));
+ connect(_main_window, SIGNAL(OpenLocationDialog()), _location_controller, SLOT(OpenLocationDialog()));
+ connect(_main_window, SIGNAL(OpenAboutDialog()), this, SLOT(OpenAboutDialog()));
+ connect(_location_controller, SIGNAL(Search(Location)), this, SLOT(Search(Location)));
+ connect(_connectivity_manager, SIGNAL(Connected()), this, SLOT(NetworkConnected()));
+ connect(_connectivity_manager, SIGNAL(Disconnected()), this, SLOT(NetworkDisconnected()));
+ connect(_connectivity_manager, SIGNAL(Error()), this, SLOT(NetworkError()));
+}
+
+MainController::~MainController()
+{
+}
+
+void MainController::Run()
+{
+ _connectivity_manager->Connect();
+}
+
+void MainController::Search()
+{
+ _location_controller->CancelAllGpsSearchs();
+ // TODO add some timer condition? How old are the loaded information
+ if (_settings->GetLocation() != _last_search_settings.GetLocation()) {
+ CancelTheaterSearch();
+ CancelMovieSearch();
+ _movie_controller->Cancel();
+ _theater_controller->Cancel();
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _cinema_schedule->Clear();
+ }
+ if (_settings->GetLocation().IsValid()) {
+ // Cancel searchs before _cinema_schedule is locked to avoid dead-locks
+ switch (_settings->GetSearchObjectsType()) {
+ case Settings::THEATERS:
+ CancelTheaterSearch();
+ break;
+ case Settings::MOVIES:
+ CancelMovieSearch();
+ break;
+ }
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ _main_window->SetLocation(_settings->GetLocation());
+ switch (_settings->GetSearchObjectsType()) {
+ case Settings::THEATERS:
+ _main_window->SetTheaterModel(_theater_proxy_model);
+ if (!_cinema_schedule->AreAllCinemasLoaded()) {
+ TheaterSearchClient *client = new TheaterSearchClient(_cinema_schedule);
+ _current_theater_search_task_id = client->GetSearchTaskId();
+ connect(client, SIGNAL(SearchStarted(int)), this, SLOT(TheatersSearchStarted(int)));
+ connect(client, SIGNAL(Reply(int, bool)), this, SLOT(TheatersSearchReply(int, bool)));
+ connect(client, SIGNAL(Error(int)), this, SLOT(TheatersSearchError(int)));
+ connect(client, SIGNAL(SearchFinished(int, bool)), this, SLOT(TheatersSearchFinished(int, bool)));
+ client->moveToThread(_search_worker);
+ CallAsync(client, &TheaterSearchClient::SearchTheater, _settings->GetLocation().GetLocationName());
+ } else {
+ TheatersSearchStarted(_current_theater_search_task_id);
+ TheatersSearchReply(_current_theater_search_task_id, true);
+ TheatersSearchFinished(_current_theater_search_task_id, true);
+ }
+ break;
+ case Settings::MOVIES:
+ _main_window->SetMovieModel(_movie_proxy_model);
+ if (!_cinema_schedule->AreAllMoviesLoaded()) {
+ MovieSearchClient *client = new MovieSearchClient(_cinema_schedule);
+ _current_movies_search_task_id = client->GetSearchTaskId();
+ connect(client, SIGNAL(SearchStarted(int)), this, SLOT(MoviesSearchStarted(int)));
+ connect(client, SIGNAL(Reply(int, bool)), this, SLOT(MoviesSearchReply(int, bool)));
+ connect(client, SIGNAL(Error(int)), this, SLOT(MoviesSearchError(int)));
+ connect(client, SIGNAL(SearchFinished(int, bool)), this, SLOT(MoviesSearchFinished(int, bool)));
+ client->moveToThread(_search_worker);
+ CallAsync(client, &MovieSearchClient::SearchMovie, _settings->GetLocation().GetLocationName());
+ } else {
+ MoviesSearchStarted(_current_movies_search_task_id);
+ MoviesSearchReply(_current_movies_search_task_id, true);
+ MoviesSearchFinished(_current_movies_search_task_id, true);
+ }
+ break;
+ }
+ _last_search_settings = *_settings;
+ } else {
+ _location_controller->OpenLocationDialog();
+ }
+}
+
+void MainController::Search(Location location)
+{
+ _settings->SetLocation(location);
+ Search();
+}
+
+void MainController::NetworkConnected()
+{
+ Search();
+}
+
+void MainController::NetworkDisconnected()
+{
+}
+
+void MainController::NetworkError()
+{
+ _main_window->SetError(tr(MSG_NETWORK_ERROR));
+}
+
+void MainController::SearchTheaters()
+{
+ _settings->SetSearchObjectsType(Settings::THEATERS);
+ Search();
+}
+
+void MainController::SearchMovies()
+{
+ _settings->SetSearchObjectsType(Settings::MOVIES);
+ Search();
+}
+
+void MainController::OpenAboutDialog()
+{
+ AboutDialog *about_dialog = new AboutDialog(_main_window);
+ connect(about_dialog, SIGNAL(ContactAuthor()), _action_controller, SLOT(ContactAuthor()));
+ about_dialog->show();
+ // dialog deletes itself
+}
+
+void MainController::CancelTheaterSearch()
+{
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _current_theater_search_task_id = TheaterSearchClient::INVALID_SEARCH_TASK_ID;
+ TheaterSearchClient::CancelAllRunningSearchs();
+}
+
+void MainController::CancelMovieSearch()
+{
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _current_movies_search_task_id = MovieSearchClient::INVALID_SEARCH_TASK_ID;
+ MovieSearchClient::CancelAllRunningSearchs();
+}
+
+void MainController::TheatersSearchStarted(int search_task_id)
+{
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ _main_window->SetBusy(true);
+ SortTheaters(true, SLOT(TheatersSortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::TheatersSearchReply(int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ SortTheaters(intermediate, SLOT(TheatersSortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::TheatersSearchError(int search_task_id)
+{
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ SortTheaters(false, SLOT(TheatersSortErrorFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::TheatersSearchFinished(int search_task_id, bool success)
+{
+ Q_UNUSED(success);
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ _main_window->SetBusy(false);
+}
+
+void MainController::SortTheaters(bool intermediate, const char *slot)
+{
+ TheaterModel *theater_model = new TheaterModel(_cinema_schedule, this);
+ QSortFilterProxyModel *sort_model = new QSortFilterProxyModel(this);
+ sort_model->setSortCaseSensitivity(Qt::CaseInsensitive);
+ sort_model->setSortRole(TheaterModel::SortRole);
+ sort_model->setDynamicSortFilter(false);
+ sort_model->setSourceModel(theater_model);
+ ItemModelSortClient *sort_client = new ItemModelSortClient(_sort_controller, this);
+ connect(sort_client, SIGNAL(SortFinished(QAbstractItemModel*,int,bool)), this, slot);
+ sort_client->Sort(sort_model, _current_theater_search_task_id, intermediate);
+ // proxy deletes itself
+}
+
+void MainController::TheatersSortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ SetTheaterModel(model);
+ if (!intermediate) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _cinema_schedule->SetAllCinemasLoaded(true);
+ if (_theater_model->rowCount() == 0) {
+ _main_window->SetError(tr(MSG_NO_THEATERS_FOUND).arg(_settings->GetLocation().GetLocationName()));
+ }
+ }
+}
+
+void MainController::TheatersSortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ Q_UNUSED(intermediate);
+ if (search_task_id != _current_theater_search_task_id) {
+ return;
+ }
+ SetTheaterModel(model);
+ if (_theater_model->rowCount() == 0) {
+ _main_window->SetError(tr(MSG_THEATERS_ERROR));
+ } else {
+ UiUtils::ShowError(tr(MSG_THEATERS_ERROR));
+ }
+}
+
+void MainController::SetTheaterModel(QAbstractItemModel *model)
+{
+ delete _theater_proxy_model->sourceModel();
+ _theater_proxy_model->setSourceModel(model);
+ delete _theater_model;
+ _theater_model = (TheaterModel *) ((QSortFilterProxyModel *) model)->sourceModel();
+}
+
+void MainController::MoviesSearchStarted(int search_task_id)
+{
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ SortMovies(true, SLOT(MoviesSortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::MoviesSearchReply(int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ SortMovies(intermediate, SLOT(MoviesSortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::MoviesSearchError(int search_task_id)
+{
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ SortMovies(false, SLOT(MoviesSortErrorFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MainController::MoviesSearchFinished(int search_task_id, bool success)
+{
+ Q_UNUSED(success);
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ _main_window->SetBusy(false);
+}
+
+void MainController::SortMovies(bool intermediate, const char *slot)
+{
+ MovieModel *movie_model = new MovieModel(_cinema_schedule, this);
+ QSortFilterProxyModel *sort_model = new QSortFilterProxyModel(this);
+ sort_model->setSortCaseSensitivity(Qt::CaseInsensitive);
+ sort_model->setSortRole(MovieModel::SortRole);
+ sort_model->setDynamicSortFilter(false);
+ sort_model->setSourceModel(movie_model);
+ ItemModelSortClient *sort_client = new ItemModelSortClient(_sort_controller, this);
+ connect(sort_client, SIGNAL(SortFinished(QAbstractItemModel*,int,bool)), this, slot);
+ sort_client->Sort(sort_model, _current_movies_search_task_id, intermediate);
+ // proxy deletes itself
+}
+
+void MainController::MoviesSortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ SetMovieModel(model);
+ if (!intermediate) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _cinema_schedule->SetAllMoviesLoaded(true);
+ if (_movie_model->rowCount() == 0) {
+ _main_window->SetError(tr(MSG_NO_MOVIES_FOUND).arg(_settings->GetLocation().GetLocationName()));
+ }
+ }
+}
+
+void MainController::MoviesSortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ Q_UNUSED(intermediate);
+ if (search_task_id != _current_movies_search_task_id) {
+ return;
+ }
+ SetMovieModel(model);
+ if (_movie_model->rowCount() == 0) {
+ _main_window->SetError(tr(MSG_MOVIES_ERROR));
+ } else {
+ UiUtils::ShowError(tr(MSG_MOVIES_ERROR));
+ }
+}
+
+void MainController::SetMovieModel(QAbstractItemModel *model)
+{
+ delete _movie_proxy_model->sourceModel();
+ _movie_proxy_model->setSourceModel(model);
+ delete _movie_model;
+ _movie_model = (MovieModel *) ((QSortFilterProxyModel *) model)->sourceModel();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MAINCONTROLLER_H
+#define MAINCONTROLLER_H
+
+#include "data/location.h"
+#include "data/settings.h"
+
+#include <QObject>
+
+class MainWindow;
+class CinemaSchedule;
+class TheaterController;
+class MovieController;
+class LocationController;
+class ActionController;
+class ItemModelSortController;
+class TheaterModel;
+class MovieModel;
+class ConnectivityManager;
+class QAbstractItemModel;
+class QSortFilterProxyModel;
+
+class MainController : public QObject
+{
+ Q_OBJECT
+public:
+ MainController(MainWindow *main_window, Settings *settings, CinemaSchedule *cinema_schedule,
+ TheaterController *theater_controller, MovieController *movie_controller,
+ LocationController *location_controller, ActionController *action_controller,
+ ItemModelSortController *sort_controller, QThread *search_worker);
+ ~MainController();
+
+public:
+ void Run();
+ void Search();
+ Q_SLOT void Search(Location location);
+
+private:
+ Q_SLOT void NetworkConnected();
+ Q_SLOT void NetworkDisconnected();
+ Q_SLOT void NetworkError();
+
+ Q_SLOT void SearchTheaters();
+ Q_SLOT void SearchMovies();
+ Q_SLOT void OpenAboutDialog();
+ void CancelTheaterSearch();
+ void CancelMovieSearch();
+
+ Q_SLOT void TheatersSearchStarted(int search_task_id);
+ Q_SLOT void TheatersSearchReply(int search_task_id, bool intermediate);
+ Q_SLOT void TheatersSearchError(int search_task_id);
+ Q_SLOT void TheatersSearchFinished(int search_task_id, bool success);
+
+ void SortTheaters(bool intermediate, const char *);
+ Q_SLOT void TheatersSortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ Q_SLOT void TheatersSortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ void SetTheaterModel(QAbstractItemModel *model);
+
+ Q_SLOT void MoviesSearchStarted(int search_task_id);
+ Q_SLOT void MoviesSearchReply(int search_task_id, bool intermediate);
+ Q_SLOT void MoviesSearchError(int search_task_id);
+ Q_SLOT void MoviesSearchFinished(int search_task_id, bool success);
+
+ void SortMovies(bool intermediate, const char *);
+ Q_SLOT void MoviesSortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ Q_SLOT void MoviesSortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ void SetMovieModel(QAbstractItemModel *model);
+
+private:
+ MainWindow *_main_window;
+ Settings *_settings;
+ CinemaSchedule *_cinema_schedule;
+ TheaterController *_theater_controller;
+ MovieController *_movie_controller;
+ LocationController *_location_controller;
+ ActionController *_action_controller;
+ ItemModelSortController *_sort_controller;
+ QThread *_search_worker;
+ ConnectivityManager *_connectivity_manager;
+ int _current_theater_search_task_id;
+ int _current_movies_search_task_id;
+ TheaterModel *_theater_model;
+ MovieModel *_movie_model;
+ QSortFilterProxyModel *_theater_proxy_model;
+ QSortFilterProxyModel *_movie_proxy_model;
+ Settings _last_search_settings;
+};
+
+#endif // MAINCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviecontroller.h"
+
+#include "data/movie.h"
+#include "data/cinemaschedule.h"
+#include "control/actioncontroller.h"
+#include "control/itemmodelsortclient.h"
+#include "ui/moviewindow.h"
+#include "ui/movieschedulemodel.h"
+#include "ui/contextdialog.h"
+#include "ui/uiutils.h"
+#include "searchclients/movieschedulesearchclient.h"
+#include "utils/assertedlocker.h"
+#include "utils/asynccall.h"
+
+#include <QSortFilterProxyModel>
+#include <iostream>
+
+static const char *MSG_NO_MOVIE_SCHEDULE_FOUND = QT_TRANSLATE_NOOP("MovieController", "No schedule found for %1.");
+static const char *MSG_MOVIE_SCHEDULE_ERROR = QT_TRANSLATE_NOOP("MovieController", "Error on fetching movie schedule.");
+
+MovieController::MovieController(MovieWindow *movie_window, CinemaSchedule *cinema_schedule,
+ ActionController *action_controller, ItemModelSortController *sort_controller,
+ QThread *search_worker)
+ : QObject(0),
+ _movie_window(movie_window),
+ _cinema_schedule(cinema_schedule),
+ _action_controller(action_controller),
+ _sort_controller(sort_controller),
+ _search_worker(search_worker),
+ _current_search_task_id(MovieScheduleSearchClient::INVALID_SEARCH_TASK_ID),
+ _movie_schedule_model(0),
+ _movie_schedule_proxy_model(new QSortFilterProxyModel(this))
+{
+ connect(_movie_window, SIGNAL(ScheduleEntrySelected(ScheduleEntryKey)), this, SLOT(ScheduleEntrySelected(ScheduleEntryKey)));
+}
+
+void MovieController::ShowMovie(MovieKey movie_key)
+{
+ CancelSearch();
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ _movie_key = movie_key;
+ const Movie *movie = ((const CinemaSchedule *) _cinema_schedule)->FindMovie(movie_key);
+ if (movie != 0) {
+ SetModel(0);
+ _movie_window->SetMovieName(movie->GetName());
+ _movie_window->SetMovieScheduleModel(_movie_schedule_proxy_model);
+ _movie_window->show();
+ MovieScheduleSearchClient *client = new MovieScheduleSearchClient(_cinema_schedule);
+ _current_search_task_id = client->GetSearchTaskId();
+ connect(client, SIGNAL(SearchStarted(int)), this, SLOT(SearchStarted(int)));
+ connect(client, SIGNAL(Reply(int, bool)), this, SLOT(Reply(int, bool)));
+ connect(client, SIGNAL(SearchFinished(int, bool)), this, SLOT(SearchFinished(int, bool)));
+ connect(client, SIGNAL(Error(int)), this, SLOT(Error(int)));
+ client->moveToThread(_search_worker);
+ CallAsync(client, &MovieScheduleSearchClient::SearchSchedule, movie->GetKey(), movie->GetTheatersUrl());
+ // search client deletes itself
+ }
+}
+
+void MovieController::Cancel()
+{
+ _movie_window->hide();
+ CancelSearch();
+}
+
+void MovieController::CancelSearch()
+{
+ SetModel(0);
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _current_search_task_id = MovieScheduleSearchClient::INVALID_SEARCH_TASK_ID;
+ MovieScheduleSearchClient::CancelAllRunningSearchs();
+}
+
+void MovieController::ScheduleEntrySelected(ScheduleEntryKey schedule_entry_key)
+{
+ ContextDialog *dialog = new ContextDialog(_cinema_schedule, _movie_window);
+ connect(dialog, SIGNAL(AddToCalendar(ScheduleEntryKey)), _action_controller, SLOT(AddToCalendar(ScheduleEntryKey)));
+ connect(dialog, SIGNAL(CallTheaterByPhone(CinemaKey)), _action_controller, SLOT(CallTheaterByPhone(CinemaKey)));
+ connect(dialog, SIGNAL(FindRouteToTheater(CinemaKey)), _action_controller, SLOT(FindRouteToTheater(CinemaKey)));
+ connect(dialog, SIGNAL(SearchMovieInWeb(MovieKey)), _action_controller, SLOT(SearchMovieInWeb(MovieKey)));
+ connect(dialog, SIGNAL(SearchTheaterInWeb(CinemaKey)), _action_controller, SLOT(SearchTheaterInWeb(CinemaKey)));
+ dialog->Show(schedule_entry_key);
+ // dialog deletes itself
+}
+
+void MovieController::SearchStarted(int search_task_id)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ _movie_window->SetBusy(true);
+}
+
+void MovieController::Reply(int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ Sort(intermediate, SLOT(SortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MovieController::Error(int search_task_id)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ Sort(false, SLOT(SortErrorFinished(QAbstractItemModel*,int,bool)));
+}
+
+void MovieController::SearchFinished(int search_task_id, bool success)
+{
+ Q_UNUSED(success);
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ _movie_window->SetBusy(false);
+}
+
+void MovieController::Sort(bool intermediate, const char *slot)
+{
+ MovieScheduleModel *movie_schedule_model = new MovieScheduleModel(_cinema_schedule, _movie_key, this);
+ movie_schedule_model->Update();
+ QSortFilterProxyModel *sort_model = new QSortFilterProxyModel(this);
+ sort_model->setSortCaseSensitivity(Qt::CaseInsensitive);
+ sort_model->setSortRole(MovieScheduleModel::SortRole);
+ sort_model->setDynamicSortFilter(false);
+ sort_model->setSourceModel(movie_schedule_model);
+ ItemModelSortClient *sort_client = new ItemModelSortClient(_sort_controller, this);
+ connect(sort_client, SIGNAL(SortFinished(QAbstractItemModel*,int,bool)), this, slot);
+ sort_client->Sort(sort_model, _current_search_task_id, intermediate);
+ // proxy deletes itself
+}
+
+void MovieController::SortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ SetModel(model);
+ if (!intermediate) {
+ if (_movie_schedule_model->rowCount() == 0) {
+ _movie_window->SetError(tr(MSG_NO_MOVIE_SCHEDULE_FOUND).arg(_movie_key.GetName()));
+ }
+ }
+}
+
+void MovieController::SortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ Q_UNUSED(intermediate);
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ SetModel(model);
+ if (_movie_schedule_model->rowCount() == 0) {
+ _movie_window->SetError(tr(MSG_MOVIE_SCHEDULE_ERROR));
+ } else {
+ UiUtils::ShowError(tr(MSG_MOVIE_SCHEDULE_ERROR));
+ }
+}
+
+void MovieController::SetModel(QAbstractItemModel *model)
+{
+ delete _movie_schedule_proxy_model->sourceModel();
+ _movie_schedule_proxy_model->setSourceModel(model);
+ delete _movie_schedule_model;
+ if (model != 0) {
+ _movie_schedule_model = (MovieScheduleModel *) ((QSortFilterProxyModel *) model)->sourceModel();
+ } else {
+ _movie_schedule_model = 0;
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIECONTROLLER_H
+#define MOVIECONTROLLER_H
+
+#include "data/scheduleentrykey.h"
+#include "data/moviekey.h"
+
+#include <QObject>
+
+class MovieWindow;
+class CinemaSchedule;
+class ActionController;
+class ItemModelSortController;
+class MovieScheduleModel;
+class QAbstractItemModel;
+class QSortFilterProxyModel;
+
+class MovieController : public QObject
+{
+ Q_OBJECT
+public:
+ MovieController(MovieWindow *movie_window, CinemaSchedule *cinema_schedule, ActionController *action_controller,
+ ItemModelSortController *sort_controller, QThread *search_worker);
+
+public:
+ Q_SLOT void ShowMovie(MovieKey movie_key);
+ void Cancel();
+
+private:
+ void CancelSearch();
+ Q_SLOT void ScheduleEntrySelected(ScheduleEntryKey schedule_entry_key);
+ Q_SLOT void SearchStarted(int search_task_id);
+ Q_SLOT void Reply(int search_task_id, bool intermediate);
+ Q_SLOT void Error(int search_task_id);
+ Q_SLOT void SearchFinished(int search_task_id, bool success);
+
+ void Sort(bool intermediate, const char *);
+ Q_SLOT void SortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ Q_SLOT void SortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ void SetModel(QAbstractItemModel *model);
+
+private:
+ MovieWindow *_movie_window;
+ CinemaSchedule *_cinema_schedule;
+ ActionController *_action_controller;
+ ItemModelSortController *_sort_controller;
+ QThread *_search_worker;
+ int _current_search_task_id;
+ MovieScheduleModel *_movie_schedule_model;
+ QSortFilterProxyModel *_movie_schedule_proxy_model;
+ MovieKey _movie_key;
+};
+
+#endif // MOVIECONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "settingscontroller.h"
+
+#include "data/settings.h"
+
+#include <QFile>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QDir>
+#include <iostream>
+
+SettingsController::SettingsController(Settings *settings)
+ : _settings(settings)
+{
+}
+
+enum State {
+ STATE_DOCUMENT,
+ STATE_SETTINGS,
+ STATE_LOCATION,
+ STATE_LOCATION_NAME,
+ STATE_PREVIOUS_LOCATIONS,
+ STATE_PREVIOUS_LOCATION,
+ STATE_PREVIOUS_LOCATION_NAME,
+ STATE_GPS,
+ STATE_SEARCH,
+};
+
+void SettingsController::Load()
+{
+ QFile file(GetSettingsFileName());
+ if (file.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader xml(&file);
+ State state = STATE_DOCUMENT;
+ Location location;
+ Settings::Locations previous_locations;
+ Location previous_location;
+ while (!xml.atEnd()) {
+ QXmlStreamReader::TokenType token = xml.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ if (state == STATE_DOCUMENT && xml.name() == "settings") {
+ state = STATE_SETTINGS;
+ } else if (state == STATE_SETTINGS && xml.name() == "location") {
+ state = STATE_LOCATION;
+ } else if (state == STATE_LOCATION && xml.name() == "name") {
+ state = STATE_LOCATION_NAME;
+ } else if (state == STATE_SETTINGS && xml.name() == "previous-locations") {
+ state = STATE_PREVIOUS_LOCATIONS;
+ } else if (state == STATE_PREVIOUS_LOCATIONS && xml.name() == "location") {
+ state = STATE_PREVIOUS_LOCATION;
+ } else if (state == STATE_PREVIOUS_LOCATION && xml.name() == "name") {
+ state = STATE_PREVIOUS_LOCATION_NAME;
+ } else if (state == STATE_SETTINGS && xml.name() == "gps") {
+ QString enabled = xml.attributes().value("enabled").toString();
+ _settings->SetGPSEnabled(enabled == "yes");
+ state = STATE_GPS;
+ } else if (state == STATE_SETTINGS && xml.name() == "search") {
+ state = STATE_SEARCH;
+ } else {
+ state = STATE_DOCUMENT;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (state == STATE_SEARCH) {
+ state = STATE_SETTINGS;
+ } else if (state == STATE_GPS) {
+ state = STATE_SETTINGS;
+ } else if (state == STATE_PREVIOUS_LOCATION_NAME) {
+ state = STATE_PREVIOUS_LOCATION;
+ } else if (state == STATE_PREVIOUS_LOCATION) {
+ if (previous_location.IsValid()) {
+ previous_locations.append(previous_location);
+ }
+ state = STATE_PREVIOUS_LOCATIONS;
+ } else if (state == STATE_PREVIOUS_LOCATIONS) {
+ state = STATE_SETTINGS;
+ } else if (state == STATE_LOCATION_NAME) {
+ state = STATE_LOCATION;
+ } else if (state == STATE_LOCATION) {
+ state = STATE_SETTINGS;
+ } else if (state == STATE_SETTINGS) {
+ state = STATE_DOCUMENT;
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ if (state == STATE_LOCATION_NAME) {
+ location.SetLocationName(xml.text().toString());
+ } else if (state == STATE_PREVIOUS_LOCATION_NAME) {
+ previous_location.SetLocationName(xml.text().toString());
+ } else if (state == STATE_SEARCH) {
+ if (xml.text() == "theaters") {
+ _settings->SetSearchObjectsType(Settings::THEATERS);
+ } else if (xml.text() == "movies") {
+ _settings->SetSearchObjectsType(Settings::MOVIES);
+ }
+ }
+ }
+ }
+ if (xml.hasError()) {
+ // TODO error message unable to read setting files?
+ file.close();
+ QDir().remove(GetSettingsFileName());
+ } else {
+ _settings->SetLocation(location);
+ _settings->SetPreviousLocations(previous_locations);
+ }
+ }
+}
+
+void SettingsController::Save()
+{
+ QFile file(GetSettingsFileName());
+ if (file.open(QIODevice::WriteOnly)) {
+ QXmlStreamWriter xml(&file);
+ xml.setAutoFormatting(true);
+ xml.writeStartDocument();
+ xml.writeStartElement("settings");
+ xml.writeStartElement("location");
+ xml.writeTextElement("name", _settings->GetLocation().GetLocationName());
+ xml.writeEndElement();
+ xml.writeStartElement("previous-locations");
+ Q_FOREACH(Location location, _settings->GetPreviousLocations()) {
+ xml.writeStartElement("location");
+ xml.writeTextElement("name", location.GetLocationName());
+ xml.writeEndElement();
+ }
+ xml.writeEndElement();
+ QString v;
+ xml.writeStartElement("gps");
+ xml.writeAttribute("enabled", _settings->IsGPSEnabled() ? "yes" : "no");
+ xml.writeEndElement();
+ switch (_settings->GetSearchObjectsType()) {
+ case Settings::THEATERS:
+ v = "theaters";
+ break;
+ case Settings::MOVIES:
+ v = "movies";
+ break;
+ }
+ xml.writeTextElement("search", v);
+ xml.writeEndElement();
+ xml.writeEndDocument();
+ } else {
+ // TODO error message unable to create file
+ std::cout << "Failed to open file " << qPrintable(GetSettingsFileName()) << std::endl;
+ }
+}
+
+QString SettingsController::GetSettingsFileName()
+{
+ QString dirpath = QDir::homePath() + "/.movie-schedule";
+ QDir().mkpath(dirpath);
+ return dirpath + "/settings.xml";
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SETTINGSCONTROLLER_H
+#define SETTINGSCONTROLLER_H
+
+#include <QString>
+
+class Settings;
+
+class SettingsController
+{
+public:
+ SettingsController(Settings *settings);
+
+ void Load();
+ void Save();
+
+private:
+ QString GetSettingsFileName();
+
+private:
+ Settings *_settings;
+};
+
+#endif // SETTINGSCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theatercontroller.h"
+
+#include "data/cinema.h"
+#include "data/cinemaschedule.h"
+#include "control/actioncontroller.h"
+#include "control/itemmodelsortclient.h"
+#include "ui/theaterwindow.h"
+#include "ui/theaterschedulemodel.h"
+#include "ui/contextdialog.h"
+#include "ui/uiutils.h"
+#include "searchclients/theaterschedulesearchclient.h"
+#include "utils/assertedlocker.h"
+#include "utils/asynccall.h"
+
+#include <QSortFilterProxyModel>
+#include <iostream>
+
+static const char *MSG_NO_THEATER_SCHEDULE_FOUND = QT_TRANSLATE_NOOP("TheaterController", "No schedule found for %1.");
+static const char *MSG_THEATER_SCHEDULE_ERROR = QT_TRANSLATE_NOOP("TheaterController", "Error on fetching theater schedule.");
+
+TheaterController::TheaterController(TheaterWindow *theater_window, CinemaSchedule *cinema_schedule, ActionController *action_controller,
+ ItemModelSortController *sort_controller, QThread *search_worker)
+ : QObject(0),
+ _theater_window(theater_window),
+ _cinema_schedule(cinema_schedule),
+ _action_controller(action_controller),
+ _sort_controller(sort_controller),
+ _search_worker(search_worker),
+ _current_search_task_id(TheaterScheduleSearchClient::INVALID_SEARCH_TASK_ID),
+ _theater_schedule_model(0),
+ _theater_schedule_proxy_model(new QSortFilterProxyModel(this))
+{
+ connect(_theater_window, SIGNAL(ScheduleEntrySelected(ScheduleEntryKey)), this, SLOT(ScheduleEntrySelected(ScheduleEntryKey)));
+}
+
+void TheaterController::ShowTheater(CinemaKey cinema_key)
+{
+ CancelSearch();
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ _cinema_key = cinema_key;
+ const Cinema *cinema = ((const CinemaSchedule *) _cinema_schedule)->FindCinema(cinema_key);
+ if (cinema != 0) {
+ SetModel(0);
+ _theater_window->SetTheaterName(cinema->GetName());
+ _theater_window->SetTheaterScheduleModel(_theater_schedule_proxy_model);
+ _theater_window->show();
+ TheaterScheduleSearchClient *client = new TheaterScheduleSearchClient(_cinema_schedule);
+ _current_search_task_id = client->GetSearchTaskId();
+ connect(client, SIGNAL(SearchStarted(int)), this, SLOT(SearchStarted(int)));
+ connect(client, SIGNAL(Reply(int,bool)), this, SLOT(Reply(int,bool)));
+ connect(client, SIGNAL(SearchFinished(int,bool)), this, SLOT(SearchFinished(int,bool)));
+ connect(client, SIGNAL(Error(int)), this, SLOT(Error(int)));
+ client->moveToThread(_search_worker);
+ CallAsync(client, &TheaterScheduleSearchClient::SearchSchedule, cinema->GetKey(), cinema->GetMoviesUrl());
+ // client deletes itself
+ }
+}
+
+void TheaterController::Cancel()
+{
+ _theater_window->hide();
+ CancelSearch();
+}
+
+void TheaterController::CancelSearch()
+{
+ SetModel(0);
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ _current_search_task_id = TheaterScheduleSearchClient::INVALID_SEARCH_TASK_ID;
+ TheaterScheduleSearchClient::CancelAllRunningSearchs();
+}
+
+void TheaterController::ScheduleEntrySelected(ScheduleEntryKey schedule_entry_key)
+{
+ ContextDialog *dialog = new ContextDialog(_cinema_schedule, _theater_window);
+ connect(dialog, SIGNAL(AddToCalendar(ScheduleEntryKey)), _action_controller, SLOT(AddToCalendar(ScheduleEntryKey)));
+ connect(dialog, SIGNAL(CallTheaterByPhone(CinemaKey)), _action_controller, SLOT(CallTheaterByPhone(CinemaKey)));
+ connect(dialog, SIGNAL(FindRouteToTheater(CinemaKey)), _action_controller, SLOT(FindRouteToTheater(CinemaKey)));
+ connect(dialog, SIGNAL(SearchMovieInWeb(MovieKey)), _action_controller, SLOT(SearchMovieInWeb(MovieKey)));
+ connect(dialog, SIGNAL(SearchTheaterInWeb(CinemaKey)), _action_controller, SLOT(SearchTheaterInWeb(CinemaKey)));
+ dialog->Show(schedule_entry_key);
+ // dialog deletes itself
+}
+
+void TheaterController::SearchStarted(int search_task_id)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ _theater_window->SetBusy(true);
+}
+
+void TheaterController::Reply(int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ Sort(intermediate, SLOT(SortFinished(QAbstractItemModel*,int,bool)));
+}
+
+void TheaterController::Error(int search_task_id)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ Sort(false, SLOT(SortErrorFinished(QAbstractItemModel*,int,bool)));
+}
+
+void TheaterController::SearchFinished(int search_task_id, bool success)
+{
+ Q_UNUSED(success);
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ _theater_window->SetBusy(false);
+}
+
+void TheaterController::Sort(bool intermediate, const char *slot)
+{
+ TheaterScheduleModel *theater_schedule_model = new TheaterScheduleModel(_cinema_schedule, _cinema_key, this);
+ theater_schedule_model->Update();
+ QSortFilterProxyModel *sort_model = new QSortFilterProxyModel(this);
+ sort_model->setSortCaseSensitivity(Qt::CaseInsensitive);
+ sort_model->setSortRole(TheaterScheduleModel::SortRole);
+ sort_model->setDynamicSortFilter(false);
+ sort_model->setSourceModel(theater_schedule_model);
+ ItemModelSortClient *sort_client = new ItemModelSortClient(_sort_controller, this);
+ connect(sort_client, SIGNAL(SortFinished(QAbstractItemModel*,int,bool)), this, slot);
+ sort_client->Sort(sort_model, _current_search_task_id, intermediate);
+ // proxy deletes itself
+}
+
+void TheaterController::SortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ SetModel(model);
+ if (!intermediate) {
+ if (_theater_schedule_model->rowCount() == 0) {
+ _theater_window->SetError(tr(MSG_NO_THEATER_SCHEDULE_FOUND).arg(_cinema_key.GetName()));
+ }
+ }
+}
+
+void TheaterController::SortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate)
+{
+ Q_UNUSED(intermediate);
+ if (search_task_id != _current_search_task_id) {
+ return;
+ }
+ SetModel(model);
+ if (_theater_schedule_model->rowCount() == 0) {
+ _theater_window->SetError(tr(MSG_THEATER_SCHEDULE_ERROR));
+ } else {
+ UiUtils::ShowError(tr(MSG_THEATER_SCHEDULE_ERROR));
+ }
+}
+
+void TheaterController::SetModel(QAbstractItemModel *model)
+{
+ delete _theater_schedule_proxy_model->sourceModel();
+ _theater_schedule_proxy_model->setSourceModel(model);
+ delete _theater_schedule_model;
+ if (model != 0) {
+ _theater_schedule_model = (TheaterScheduleModel *) ((QSortFilterProxyModel *) model)->sourceModel();
+ } else {
+ _theater_schedule_model = 0;
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERCONTROLLER_H
+#define THEATERCONTROLLER_H
+
+#include "data/scheduleentrykey.h"
+#include "data/cinemakey.h"
+
+#include <QObject>
+
+class TheaterWindow;
+class CinemaSchedule;
+class TheaterScheduleModel;
+class ItemModelSortController;
+class ScheduleEntry;
+class ActionController;
+class QAbstractItemModel;
+class QSortFilterProxyModel;
+
+class TheaterController : public QObject
+{
+ Q_OBJECT
+public:
+ TheaterController(TheaterWindow *theater_window, CinemaSchedule *cinema_schedule, ActionController *action_controller,
+ ItemModelSortController *sort_controller, QThread *search_worker);
+
+public:
+ Q_SLOT void ShowTheater(CinemaKey cinema_key);
+ void Cancel();
+
+private:
+ void CancelSearch();
+ Q_SLOT void ScheduleEntrySelected(ScheduleEntryKey schedule_entry_key);
+ Q_SLOT void SearchStarted(int search_task_id);
+ Q_SLOT void Reply(int search_task_id, bool intermediate);
+ Q_SLOT void Error(int search_task_id);
+ Q_SLOT void SearchFinished(int search_task_id, bool success);
+
+ void Sort(bool intermediate, const char *);
+ Q_SLOT void SortFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ Q_SLOT void SortErrorFinished(QAbstractItemModel *model, int search_task_id, bool intermediate);
+ void SetModel(QAbstractItemModel *model);
+
+private:
+ TheaterWindow *_theater_window;
+ CinemaSchedule *_cinema_schedule;
+ ActionController *_action_controller;
+ ItemModelSortController *_sort_controller;
+ QThread *_search_worker;
+ int _current_search_task_id;
+ TheaterScheduleModel *_theater_schedule_model;
+ QSortFilterProxyModel *_theater_schedule_proxy_model;
+ CinemaKey _cinema_key;
+};
+
+#endif // THEATERCONTROLLER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "cinema.h"
+
+Cinema::Cinema()
+{
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CINEMA_H
+#define CINEMA_H
+
+#include "cinemakey.h"
+
+#include <QString>
+
+class Cinema
+{
+public:
+ Cinema();
+
+ CinemaKey GetKey() const { return CinemaKey(_name, _address); }
+
+ bool IsValid() const { return !_name.isEmpty(); }
+
+ QString GetName() const { return _name; }
+ void SetName(const QString &name) { _name = name; }
+
+ QString GetAddress() const { return _address; }
+ void SetAddress(const QString &address) { _address = address; }
+
+ QString GetMoviesUrl() const { return _movies_url; }
+ void SetMoviesUrl(const QString &movies_url) { _movies_url = movies_url; }
+
+ QString GetTelephone() const { return _telephone; }
+ void SetTelephone(const QString &telephone) { _telephone = telephone; }
+
+private:
+ QString _name;
+ QString _address;
+ QString _movies_url;
+ QString _telephone;
+};
+
+#endif // CINEMA_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "cinemakey.h"
+
+#include <qhash.h>
+
+CinemaKey::CinemaKey(const QString &name, const QString &address)
+ : _name(name),
+ _address(address)
+{
+}
+
+bool operator==(const CinemaKey &lhs, const CinemaKey &rhs)
+{
+ return lhs.GetName() == rhs.GetName()
+ && lhs.GetAddress() == rhs.GetAddress();
+}
+
+uint qHash(const CinemaKey &key)
+{
+ return qHash(key.GetName()) + qHash(key.GetAddress());
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CINEMAKEY_H
+#define CINEMAKEY_H
+
+#include <QString>
+#include <QMetaType>
+
+class CinemaKey
+{
+public:
+ CinemaKey() {}
+ CinemaKey(const QString &name, const QString &address);
+
+ QString GetName() const { return _name; }
+ void SetName(const QString &name) { _name = name; }
+
+ QString GetAddress() const { return _address; }
+ void SetAddress(const QString &address) { _address = address; }
+
+private:
+ QString _name;
+ QString _address;
+};
+
+bool operator==(const CinemaKey &lhs, const CinemaKey &rhs);
+
+uint qHash(const CinemaKey &);
+
+Q_DECLARE_METATYPE(CinemaKey);
+
+#endif // CINEMAKEY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "cinemaschedule.h"
+
+#include "cinema.h"
+#include "movie.h"
+
+CinemaSchedule::CinemaSchedule()
+ : _lock(),
+ _all_cinemas_loaded(false),
+ _all_movies_loaded(false)
+{
+}
+
+void CinemaSchedule::Clear()
+{
+ _lock.AssertLockedForWrite();
+ _schedules.clear();
+ foreach (Movie *movie, _movies.values()) {
+ delete movie;
+ }
+ _movies.clear();
+ _all_movies_loaded = false;
+ foreach (Cinema *cinema, _cinemas.values()) {
+ delete cinema;
+ }
+ _cinemas.clear();
+ _all_cinemas_loaded = false;
+}
+
+Cinema *CinemaSchedule::FindCinema(const CinemaKey &key)
+{
+ _lock.AssertLockedForWrite();
+ if (!_cinemas.contains(key)) {
+ return 0;
+ }
+ return _cinemas[key];
+}
+
+const Cinema *CinemaSchedule::FindCinema(const CinemaKey &key) const
+{
+ _lock.AssertLockedForRead();
+ if (!_cinemas.contains(key)) {
+ return 0;
+ }
+ return _cinemas[key];
+}
+
+Cinema *CinemaSchedule::AddCinema(const CinemaKey &key)
+{
+ _lock.AssertLockedForWrite();
+ Cinema *cinema = 0;
+ if (_cinemas.contains(key))
+ {
+ cinema = _cinemas[key];
+ if (cinema != 0) {
+ return cinema;
+ }
+ }
+ cinema = new Cinema();
+ cinema->SetName(key.GetName());
+ cinema->SetAddress(key.GetAddress());
+ _cinemas[key] = cinema;
+ return cinema;
+}
+
+Movie *CinemaSchedule::FindMovie(const MovieKey &key)
+{
+ _lock.AssertLockedForWrite();
+ if (!_movies.contains(key)) {
+ return 0;
+ }
+ return _movies[key];
+}
+
+const Movie *CinemaSchedule::FindMovie(const MovieKey &key) const
+{
+ _lock.AssertLockedForRead();
+ if (!_movies.contains(key)) {
+ return 0;
+ }
+ return _movies[key];
+}
+
+Movie *CinemaSchedule::AddMovie(const MovieKey &key)
+{
+ _lock.AssertLockedForWrite();
+ Movie *movie = 0;
+ if (_movies.contains(key)){
+ movie = _movies[key];
+ if (movie != 0) {
+ return movie;
+ }
+ }
+ movie = new Movie();
+ movie->SetName(key.GetName());
+ _movies[key] = movie;
+ return movie;
+}
+
+const CinemaSchedule::ScheduleDates CinemaSchedule::GetScheduleDates() const
+{
+ _lock.AssertLockedForRead();
+ ScheduleDates result;
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ result |= entry.GetDate();
+ }
+ return result;
+}
+
+const CinemaSchedule::ScheduleDates CinemaSchedule::GetScheduleDates(const Cinema *cinema) const
+{
+ _lock.AssertLockedForRead();
+ ScheduleDates result;
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetCinema() == cinema) {
+ result |= entry.GetDate();
+ }
+ }
+ return result;
+}
+
+const CinemaSchedule::ScheduleDates CinemaSchedule::GetScheduleDates(const Movie *movie) const
+{
+ _lock.AssertLockedForRead();
+ ScheduleDates result;
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetMovie() == movie) {
+ result |= entry.GetDate();
+ }
+ }
+ return result;
+}
+
+ScheduleEntry CinemaSchedule::FindScheduleEntry(const ScheduleEntryKey &schedule_entry_key) const
+{
+ _lock.AssertLockedForRead();
+ const Cinema *cinema = FindCinema(schedule_entry_key.GetCinemaKey());
+ const Movie *movie = FindMovie(schedule_entry_key.GetMovieKey());
+ ScheduleEntry schedule_entry;
+ if (cinema != 0 && movie != 0) {
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetCinema() == cinema && entry.GetMovie() == movie
+ && entry.GetStartTime() == schedule_entry_key.GetStartTime()
+ && entry.GetDate() == schedule_entry_key.GetDate()) {
+ schedule_entry = entry;
+ break;
+ }
+ }
+ }
+ return schedule_entry;
+}
+
+const CinemaSchedule::Schedules CinemaSchedule::GetSchedules(const Cinema *cinema) const
+{
+ _lock.AssertLockedForRead();
+ Schedules result;
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetCinema() == cinema) {
+ result |= entry;
+ }
+ }
+ return result;
+}
+
+const CinemaSchedule::Schedules CinemaSchedule::GetSchedules(const Movie *movie) const
+{
+ _lock.AssertLockedForRead();
+ Schedules result;
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetMovie() == movie) {
+ result |= entry;
+ }
+ }
+ return result;
+}
+
+const CinemaSchedule::ScheduleKeys CinemaSchedule::GetScheduleKeys(const CinemaKey &cinema_key) const
+{
+ _lock.AssertLockedForRead();
+ ScheduleKeys result;
+ const Cinema *cinema = FindCinema(cinema_key);
+ if (cinema != 0) {
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetCinema() == cinema) {
+ result |= entry.GetKey();
+ }
+ }
+ }
+ return result;
+}
+
+const CinemaSchedule::ScheduleKeys CinemaSchedule::GetScheduleKeys(const MovieKey &movie_key) const
+{
+ _lock.AssertLockedForRead();
+ ScheduleKeys result;
+ const Movie *movie = FindMovie(movie_key);
+ if (movie != 0) {
+ Q_FOREACH(const ScheduleEntry &entry, _schedules) {
+ if (entry.GetMovie() == movie) {
+ result |= entry.GetKey();
+ }
+ }
+ }
+ return result;
+}
+
+void CinemaSchedule::AddSchedule(const Cinema *cinema, const Movie *movie, const QTime &start_time, const QDate &date)
+{
+ _lock.AssertLockedForWrite();
+ _schedules |= ScheduleEntry(cinema, movie, start_time, date);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CINEMASCHEDULE_H
+#define CINEMASCHEDULE_H
+
+#include "location.h"
+#include "cinemakey.h"
+#include "moviekey.h"
+#include "scheduleentrykey.h"
+#include "scheduleentry.h"
+#include "utils/assertedlock.h"
+
+#include <QHash>
+#include <QSet>
+#include <QReadWriteLock>
+
+class Cinema;
+class Movie;
+
+class CinemaSchedule
+{
+ Q_DISABLE_COPY(CinemaSchedule);
+public:
+ typedef QHash<CinemaKey, Cinema *> Cinemas;
+ typedef QHash<MovieKey, Movie *> Movies;
+ typedef QSet<QDate> ScheduleDates;
+ typedef QSet<ScheduleEntry> Schedules;
+ typedef QSet<ScheduleEntryKey> ScheduleKeys;
+public:
+ CinemaSchedule();
+
+ AssertedLock *GetLock() const { return const_cast<AssertedLock *>(&_lock); }
+
+ void Clear();
+
+ bool AreAllCinemasLoaded() const { _lock.AssertLockedForRead(); return _all_cinemas_loaded; }
+ void SetAllCinemasLoaded(bool all_cinemas_loaded) { _lock.AssertLockedForWrite(); _all_cinemas_loaded = all_cinemas_loaded; }
+ const Cinemas GetCinemas() const { _lock.AssertLockedForRead(); return _cinemas; }
+ Cinema *FindCinema(const CinemaKey &);
+ const Cinema *FindCinema(const CinemaKey &) const;
+ Cinema *AddCinema(const CinemaKey &);
+
+ bool AreAllMoviesLoaded() const { _lock.AssertLockedForRead(); return _all_movies_loaded; }
+ void SetAllMoviesLoaded(bool all_movies_loaded) { _lock.AssertLockedForWrite(); _all_movies_loaded = all_movies_loaded; }
+ const Movies GetMovies() const { _lock.AssertLockedForRead(); return _movies; }
+ Movie *FindMovie(const MovieKey &);
+ const Movie *FindMovie(const MovieKey &) const;
+ Movie *AddMovie(const MovieKey &);
+
+ const ScheduleDates GetScheduleDates() const;
+ const ScheduleDates GetScheduleDates(const Cinema *) const;
+ const ScheduleDates GetScheduleDates(const Movie *) const;
+ ScheduleEntry FindScheduleEntry(const ScheduleEntryKey &) const;
+ const Schedules GetSchedules() const { _lock.AssertLockedForRead(); return _schedules; }
+ const Schedules GetSchedules(const Cinema *) const;
+ const Schedules GetSchedules(const Movie *) const;
+ const ScheduleKeys GetScheduleKeys(const CinemaKey &) const;
+ const ScheduleKeys GetScheduleKeys(const MovieKey &) const;
+ void AddSchedule(const Cinema *, const Movie *, const QTime &start_time, const QDate &date);
+
+private:
+ AssertedLock _lock;
+ bool _all_cinemas_loaded;
+ Cinemas _cinemas;
+ bool _all_movies_loaded;
+ Movies _movies;
+ Schedules _schedules;
+};
+
+inline int qHash(const QDate &date) { return qHash(date.toJulianDay()); }
+
+#endif // CINEMASCHEDULE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "location.h"
+
+Location::Location()
+{
+}
+
+bool operator==(const Location &lhs, const Location &rhs)
+{
+ return lhs.GetLocationName() == rhs.GetLocationName();
+}
+
+bool operator!=(const Location &lhs, const Location &rhs)
+{
+ return !(lhs == rhs);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef LOCATION_H
+#define LOCATION_H
+
+#include <QString>
+#include <QMetaType>
+
+class Location
+{
+public:
+ Location();
+
+ bool IsValid() const { return !_location_name.isEmpty(); }
+
+ QString GetLocationName() const { return _location_name; }
+ void SetLocationName(const QString &location_name) { _location_name = location_name; }
+
+private:
+ QString _location_name;
+};
+
+bool operator==(const Location &lhs, const Location &rhs);
+
+bool operator!=(const Location &lhs, const Location &rhs);
+
+Q_DECLARE_METATYPE(Location);
+
+#endif // LOCATION_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "movie.h"
+
+Movie::Movie()
+ : _rate(-1.0)
+{
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIE_H
+#define MOVIE_H
+
+#include "data/moviekey.h"
+
+#include <QString>
+#include <QTime>
+
+class Movie
+{
+public:
+ Movie();
+
+ MovieKey GetKey() const { return MovieKey(_name); }
+
+ QString GetName() const { return _name; }
+ void SetName(const QString &name) { _name = name; }
+
+ QString GetTheatersUrl() const { return _theaters_url; }
+ void SetTheatersUrl(const QString &theaters_url) { _theaters_url = theaters_url; }
+
+ QTime GetDuration() const { return _duration; }
+ void SetDuration(const QTime &duration) { _duration = duration; }
+
+ QString GetComment() const { return _comment; }
+ void SetComment(const QString &age) { _comment = age; }
+
+ double GetRate() const { return _rate; }
+ void SetRate(double rate) { _rate = rate; }
+
+private:
+ QString _name;
+ QString _theaters_url;
+ QTime _duration;
+ QString _comment;
+ double _rate;
+};
+
+#endif // MOVIE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviekey.h"
+
+#include <qhash.h>
+
+MovieKey::MovieKey(const QString &name)
+ : _name(name)
+{
+}
+
+bool operator==(const MovieKey &lhs, const MovieKey &rhs)
+{
+ return lhs.GetName() == rhs.GetName();
+}
+
+uint qHash(const MovieKey &key)
+{
+ return qHash(key.GetName());
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIEKEY_H
+#define MOVIEKEY_H
+
+#include <QString>
+#include <QMetaType>
+
+class MovieKey
+{
+public:
+ MovieKey() {}
+ MovieKey(const QString &name);
+
+ QString GetName() const { return _name; }
+ void SetName(const QString &name) { _name = name; }
+
+private:
+ QString _name;
+};
+
+bool operator==(const MovieKey &lhs, const MovieKey &rhs);
+
+uint qHash(const MovieKey &);
+
+Q_DECLARE_METATYPE(MovieKey);
+
+#endif // MOVIEKEY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "scheduleentry.h"
+
+#include "data/cinema.h"
+#include "data/movie.h"
+
+#include <qhash.h>
+
+
+ScheduleEntry::ScheduleEntry()
+ : _cinema(0),
+ _movie(0)
+{
+}
+
+ScheduleEntry::ScheduleEntry(const Cinema *cinema, const Movie *movie, const QTime &start_time, const QDate &date)
+ : _cinema(cinema),
+ _movie(movie),
+ _start_time(start_time),
+ _date(date)
+{
+}
+
+ScheduleEntryKey ScheduleEntry::GetKey() const
+{
+ return ScheduleEntryKey(_cinema->GetKey(), _movie->GetKey(), _start_time, _date);
+}
+
+bool operator==(const ScheduleEntry &lhs, const ScheduleEntry &rhs)
+{
+ return lhs.GetCinema() == rhs.GetCinema()
+ && lhs.GetMovie() == rhs.GetMovie()
+ && lhs.GetStartTime() == rhs.GetStartTime()
+ && lhs.GetDate() == rhs.GetDate();
+}
+
+uint qHash(const ScheduleEntry &key)
+{
+ static QTime midnight(0, 0);
+ return qHash(key.GetCinema()) + qHash(key.GetMovie()) + qHash(-key.GetStartTime().secsTo(midnight)) + qHash(key.GetDate().toJulianDay());
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SCHEDULEENTRY_H
+#define SCHEDULEENTRY_H
+
+#include "scheduleentrykey.h"
+
+#include <QString>
+#include <QDate>
+
+class Cinema;
+class Movie;
+
+class ScheduleEntry
+{
+public:
+ ScheduleEntry();
+ ScheduleEntry(const Cinema *cinema, const Movie *movie, const QTime &start_time, const QDate &date);
+
+ ScheduleEntryKey GetKey() const;
+
+ bool IsValid() const { return _cinema != 0 && _movie != 0; }
+
+ const Cinema *GetCinema() const { return _cinema; }
+ void SetCinema(const Cinema *cinema) { _cinema = cinema; }
+
+ const Movie *GetMovie() const { return _movie; }
+ void SetMovie(const Movie *movie) { _movie = movie; }
+
+ QTime GetStartTime() const { return _start_time; }
+ void SetStartTime(const QTime &start_time) { _start_time = start_time; }
+
+ QDate GetDate() const { return _date; }
+ void SetDate(const QDate &date) { _date = date; }
+
+private:
+ const Cinema *_cinema;
+ const Movie *_movie;
+ QTime _start_time;
+ QDate _date;
+};
+
+bool operator==(const ScheduleEntry &lhs, const ScheduleEntry &rhs);
+
+uint qHash(const ScheduleEntry &);
+
+#endif // SCHEDULEENTRY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "scheduleentrykey.h"
+
+#include <qhash.h>
+
+ScheduleEntryKey::ScheduleEntryKey(const CinemaKey &cinema_key, const MovieKey &movie_key, const QTime &start_time, const QDate &date) :
+ _cinema_key(cinema_key),
+ _movie_key(movie_key),
+ _start_time(start_time),
+ _date(date)
+{
+}
+
+bool operator==(const ScheduleEntryKey &lhs, const ScheduleEntryKey &rhs)
+{
+ return lhs.GetCinemaKey() == rhs.GetCinemaKey()
+ && lhs.GetMovieKey() == rhs.GetMovieKey()
+ && lhs.GetStartTime() == rhs.GetStartTime()
+ && lhs.GetDate() == rhs.GetDate();
+}
+
+uint qHash(const ScheduleEntryKey &key)
+{
+ static QTime midnight(0, 0);
+ return qHash(key.GetCinemaKey()) + qHash(key.GetMovieKey()) + qHash(-key.GetStartTime().secsTo(midnight)) + qHash(key.GetDate().toJulianDay());
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SCHEDULEENTRYKEY_H
+#define SCHEDULEENTRYKEY_H
+
+#include "data/cinemakey.h"
+#include "data/moviekey.h"
+
+#include <QTime>
+#include <QDate>
+#include <QMetaType>
+
+class ScheduleEntryKey
+{
+public:
+ ScheduleEntryKey() {}
+ ScheduleEntryKey(const CinemaKey &cinema_key, const MovieKey &movie_key, const QTime &start_time, const QDate &date);
+
+ CinemaKey GetCinemaKey() const { return _cinema_key; }
+ void SetCinemaKey(const CinemaKey &cinema_key) { _cinema_key = cinema_key; }
+
+ MovieKey GetMovieKey() const { return _movie_key; }
+ void SetMovieKey(const MovieKey &movie_key) { _movie_key = movie_key; }
+
+ QTime GetStartTime() const { return _start_time; }
+ void SetStartTime(const QTime &start_time) { _start_time = start_time; }
+
+ QDate GetDate() const { return _date; }
+ void SetDate(const QDate &date) { _date = date; }
+
+private:
+ CinemaKey _cinema_key;
+ MovieKey _movie_key;
+ QTime _start_time;
+ QDate _date;
+};
+
+Q_DECLARE_METATYPE(ScheduleEntryKey);
+
+bool operator==(const ScheduleEntryKey &lhs, const ScheduleEntryKey &rhs);
+
+uint qHash(const ScheduleEntryKey &);
+
+#endif // SCHEDULEENTRYKEY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "settings.h"
+
+Settings::Settings()
+ : _location(),
+ _previous_locations(),
+ _gps_enabled(true),
+ _search_objects_type(MOVIES)
+{
+}
+
+void Settings::SetPreviousLocations(const Locations &previous_locations)
+{
+ _previous_locations = previous_locations;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include "location.h"
+
+#include <QString>
+#include <QList>
+
+class Settings
+{
+public:
+ typedef QList<Location> Locations;
+
+ enum SearchObjectsType {
+ THEATERS,
+ MOVIES
+ };
+
+public:
+ Settings();
+
+ Location GetLocation() const { return _location; }
+ void SetLocation(const Location &location) { _location = location; }
+
+ Locations GetPreviousLocations() const { return _previous_locations; }
+ void SetPreviousLocations(const Locations &previous_locations);
+
+ bool IsGPSEnabled() const { return _gps_enabled; }
+ void SetGPSEnabled(bool gps_enabled) { _gps_enabled = gps_enabled; }
+
+ SearchObjectsType GetSearchObjectsType() const { return _search_objects_type; }
+ void SetSearchObjectsType(SearchObjectsType search_objects_type) { _search_objects_type = search_objects_type; }
+
+private:
+ Location _location;
+ Locations _previous_locations;
+ bool _gps_enabled;
+ SearchObjectsType _search_objects_type;
+};
+
+#endif // SETTINGS_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "movieschedule.h"
+
+int main(int argc, char *argv[])
+{
+ MovieSchedule movie_schedule;
+ int rc = movie_schedule.exec(argc, argv);
+ return rc;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "movieschedule.h"
+
+#include "data/settings.h"
+#include "data/cinemaschedule.h"
+#include "control/settingscontroller.h"
+#include "control/maincontroller.h"
+#include "control/theatercontroller.h"
+#include "control/moviecontroller.h"
+#include "control/locationcontroller.h"
+#include "control/actioncontroller.h"
+#include "control/itemmodelsortcontroller.h"
+#include "ui/mainwindow.h"
+#include "ui/moviemodel.h"
+#include "ui/moviewindow.h"
+#include "ui/theatermodel.h"
+#include "ui/theaterwindow.h"
+#include "ui/ratingprovider.h"
+#include "ui/styleutils.h"
+
+#include <QApplication>
+#include <QTranslator>
+#include <QLocale>
+#include <QThread>
+#include <iostream>
+
+#ifdef MAEMO_SDK
+#include <glib-object.h>
+#endif
+
+#define _STRINGIZE_(x) #x
+#define _STRINGIZE(x) _STRINGIZE_(x)
+
+class ControllerThread : public QThread
+{
+public:
+ void run()
+ {
+ exec();
+ }
+
+ void quit()
+ {
+ QThread::quit();
+ wait();
+ }
+};
+
+MovieSchedule::MovieSchedule()
+{
+}
+
+int MovieSchedule::exec(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+#ifdef MAEMO_SDK
+ g_type_init();
+#endif
+
+ qRegisterMetaType<Location>();
+
+ StyleUtilsSingleton style_utils_singleton;
+ (void) style_utils_singleton;
+
+ QString app_dir;
+#ifdef DEFAULT_PREFIX
+ app_dir = QApplication::applicationDirPath();
+#else
+ app_dir = _STRINGIZE(DATADIR) "/movie-schedule";
+#endif
+ //std::cout << "app_dir = " << qPrintable(app_dir) << std::endl;
+
+ QString locale = QLocale::system().name();
+ //std::cout << "locale: " << qPrintable(locale) << std::endl;
+
+#if 1
+ QTranslator translator;
+ translator.load(app_dir + "/translations/movie-schedule_" + locale);
+ app.installTranslator(&translator);
+#endif
+
+ RatingSingleton rating_singleton;
+ (void) rating_singleton;
+
+ CinemaSchedule cinema_schedule;
+
+ MainWindow main_window(&cinema_schedule);
+ main_window.show();
+
+ Settings settings;
+ SettingsController settings_controller(&settings);
+ settings_controller.Load();
+
+ ActionController action_controller(&cinema_schedule);
+
+ ControllerThread sort_worker;
+ sort_worker.start();
+
+ ControllerThread search_worker;
+ search_worker.start();
+
+ ItemModelSortController sort_controller(&cinema_schedule);
+ sort_controller.moveToThread(&sort_worker);
+
+ TheaterWindow theater_window(&cinema_schedule, &main_window);
+ TheaterController theater_controller(&theater_window, &cinema_schedule, &action_controller,
+ &sort_controller, &search_worker);
+
+ MovieWindow movie_window(&cinema_schedule, &main_window);
+ MovieController movie_controller(&movie_window, &cinema_schedule, &action_controller,
+ &sort_controller, &search_worker);
+
+ LocationController location_controller(&main_window, &settings);
+
+ MainController main_controller(&main_window, &settings, &cinema_schedule, &theater_controller,
+ &movie_controller, &location_controller, &action_controller,
+ &sort_controller, &search_worker);
+
+ main_controller.Run();
+
+ int rc = app.exec();
+
+ if (rc == 0) {
+ settings_controller.Save();
+ }
+
+ search_worker.quit();
+
+ sort_worker.quit();
+
+ return rc;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIESCHEDULE_H
+#define MOVIESCHEDULE_H
+
+#include <QObject>
+
+class MovieSchedule : public QObject
+{
+ Q_OBJECT
+
+public:
+ MovieSchedule();
+
+public:
+ int exec(int argc, char *argv[]);
+
+};
+
+#endif // MOVIESCHEDULE_H
--- /dev/null
+<RCC>
+ <qresource prefix="/">
+ <file>resources/0.png</file>
+ <file>resources/1.png</file>
+ <file>resources/2.png</file>
+ <file>resources/3.png</file>
+ <file>resources/4.png</file>
+ <file>resources/5.png</file>
+ <file>resources/6.png</file>
+ <file>resources/7.png</file>
+ <file>resources/8.png</file>
+ <file>resources/9.png</file>
+ <file>resources/10.png</file>
+ </qresource>
+</RCC>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 5.2839726,0.15169464 L 5.1919919,7.5673741 L 1.9269333,9.8748291 L 3.1417391,6.1047421 L 0.083779711,3.8008 L 3.8538667,3.8426899 L 5.2839726,0.15169464 z "
+ style="fill:yellow;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3722" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 16.071131,0.15169464 L 15.97915,7.5673741 L 12.714091,9.8748291 L 13.928897,6.1047421 L 10.870938,3.8008 L 14.641025,3.8426899 L 16.071131,0.15169464 z "
+ style="fill:yellow;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3722" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 26.922499,0.15169464 L 26.830518,7.5673741 L 23.565459,9.8748291 L 24.780265,6.1047421 L 21.722306,3.8008 L 25.492393,3.8426899 L 26.922499,0.15169464 z "
+ style="fill:yellow;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3722" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 37.709657,0.15169464 L 37.617676,7.5673741 L 34.352617,9.8748291 L 35.567423,6.1047421 L 32.509464,3.8008 L 36.279551,3.8426899 L 37.709657,0.15169464 z "
+ style="fill:yellow;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3722" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="54"
+ height="10"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 48.496815,0.15169464 L 48.404834,7.5673741 L 45.139775,9.8748291 L 46.354581,6.1047421 L 43.296622,3.8008 L 47.066709,3.8426899 L 48.496815,0.15169464 z "
+ style="fill:yellow;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path3722" />
+ <path
+ d="M 8.3937876,9.9252174 L 5.2446694,7.5817439 L 2.0549565,9.8696566 L 3.3106014,6.150494 L 0.14899204,3.8239007 L 4.074141,3.8688056 L 5.3098715,0.14297911 L 6.4801023,3.8898943 L 10.405435,3.9138002 L 7.2035286,6.1846163 L 8.3937876,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path2827" />
+ <path
+ d="M 19.177463,9.9252174 L 16.028344,7.5817439 L 12.838632,9.8696566 L 14.094276,6.150494 L 10.932667,3.8239007 L 14.857815,3.8688056 L 16.093546,0.14297911 L 17.263777,3.8898943 L 21.18911,3.9138002 L 17.987203,6.1846163 L 19.177463,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3714" />
+ <path
+ d="M 29.961137,9.9252174 L 26.812019,7.5817439 L 23.622306,9.8696566 L 24.87795,6.150494 L 21.716342,3.8239007 L 25.64149,3.8688056 L 26.877221,0.14297911 L 28.047452,3.8898943 L 31.972785,3.9138002 L 28.770878,6.1846163 L 29.961137,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3716" />
+ <path
+ d="M 40.744811,9.9252174 L 37.595693,7.5817439 L 34.405981,9.8696566 L 35.661625,6.150494 L 32.500016,3.8239007 L 36.425164,3.8688056 L 37.660895,0.14297911 L 38.831126,3.8898943 L 42.756459,3.9138002 L 39.554552,6.1846163 L 40.744811,9.9252174 z "
+ style="fill:yellow;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3718" />
+ <path
+ d="M 51.528488,9.9252174 L 48.37937,7.5817439 L 45.189657,9.8696566 L 46.445301,6.150494 L 43.283692,3.8239007 L 47.208841,3.8688056 L 48.444571,0.14297911 L 49.614802,3.8898943 L 53.540135,3.9138002 L 50.338228,6.1846163 L 51.528488,9.9252174 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.29798406;stroke-linejoin:round;stroke-miterlimit:1;stroke-dasharray:none;stroke-opacity:1"
+ id="path3720" />
+</svg>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "abstractsearchclient.h"
+
+#include <QMutexLocker>
+#include <iostream>
+
+AbstractSearchClient::AbstractSearchClient(QObject *parent)
+ : QObject(parent),
+ _network(new QNetworkAccessManager(this)),
+ _search_task_id(INVALID_SEARCH_TASK_ID),
+ _start(0)
+{
+ connect(_network, SIGNAL(finished(QNetworkReply *)),
+ this, SLOT(ReplyFinished(QNetworkReply*)));
+ {
+ QMutexLocker locker(&_next_search_task_id_mutex);
+ _search_task_id = _next_search_task_id++;
+ }
+}
+
+AbstractSearchClient::~AbstractSearchClient()
+{
+}
+
+void AbstractSearchClient::Search(const QUrl &url, int start)
+{
+ _start = start;
+ if (start == 0) {
+ emit SearchStarted(_search_task_id);
+ }
+ QNetworkRequest request;
+ QUrl xurl(url);
+ if (_start != 0) {
+ xurl.addQueryItem("start", QString::number(_start));
+ }
+ FixLocation(&xurl);
+ //std::cout << "URL: " << qPrintable(QString(xurl.toEncoded())) << std::endl;
+ request.setUrl(xurl);
+ //request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.1.9) Gecko/20100401 Ubuntu/9.10 (karmic) Firefox/3.5.9");
+ request.setRawHeader("User-Agent", "Mozilla/5.0");
+ //request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ request.setRawHeader("Accept", "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ request.setRawHeader("Accept-Language", "en-gb;q=1.0,en;q=0.9,de-de;q=0.5,de;q=0.3");
+ //request.setRawHeader("Accept-Encoding", "gzip,deflate");
+ request.setRawHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
+ request.setRawHeader("Keep-Alive", "300");
+ request.setRawHeader("Connection", "keep-alive");
+ request.setRawHeader("Cache-Control", "max-age=0");
+ QNetworkReply *reply = _network->get(request);
+ connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(DownloadProgress(qint64,qint64)));
+ connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(NetworkError(QNetworkReply::NetworkError)));
+}
+
+void AbstractSearchClient::DownloadProgress(qint64 a,qint64 b)
+{
+ //std::cout << "Search Progress of " << qPrintable(objectName()) << " - " << a << ", " << b << std::endl;
+ //sleep(1);
+ emit Progress(_search_task_id, a, b);
+}
+
+void AbstractSearchClient::NetworkError(QNetworkReply::NetworkError error)
+{
+ emit SearchFinished(_search_task_id, false);
+ std::cout << "ERROR: " << error << std::endl;
+ emit Error(_search_task_id);
+ sender()->deleteLater();
+ deleteLater();
+}
+
+void AbstractSearchClient::FixLocation(QUrl *url)
+{
+ // Try to fix the Google url which returns
+ // wrong locations in some links
+ if (_location.isNull()) {
+ // Fetch location from url on first call (which is still correct)
+ if (url->hasQueryItem("loc")) {
+ _location = url->queryItemValue("loc");
+ } else if (url->hasQueryItem("near")) {
+ _location = url->queryItemValue("near");
+ } else if (url->hasQueryItem("defaultloc")) {
+ _location = url->queryItemValue("defaultloc");
+ }
+ } else {
+ // Replace with fetched location in later calls
+ if (url->hasQueryItem("loc")) {
+ url->removeAllQueryItems("loc");
+ url->addQueryItem("loc", _location);
+ }
+ if (url->hasQueryItem("near")) {
+ url->removeAllQueryItems("near");
+ url->addQueryItem("near", _location);
+ }
+ if (url->hasQueryItem("defaultloc")) {
+ url->removeAllQueryItems("defaultloc");
+ url->addQueryItem("defaultloc", _location);
+ }
+ }
+}
+
+QMutex AbstractSearchClient::_next_search_task_id_mutex;
+int AbstractSearchClient::_next_search_task_id = 1;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ABSTRACTSEARCHCLIENT_H
+#define ABSTRACTSEARCHCLIENT_H
+
+#include <QObject>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QMutex>
+
+class AbstractSearchClient : public QObject
+{
+ Q_OBJECT
+public:
+ static const int INVALID_SEARCH_TASK_ID = -1;
+
+public:
+ explicit AbstractSearchClient(QObject *parent = 0);
+ virtual ~AbstractSearchClient();
+
+ int GetSearchTaskId() const { return _search_task_id; }
+
+protected:
+ int GetStartIndex() { return _start; }
+
+ virtual void Search(const QUrl &url, int start);
+
+public:
+ Q_SIGNAL void SearchStarted(int search_task_id);
+ Q_SIGNAL void Progress(int search_task_id, qint64, qint64);
+ Q_SIGNAL void Reply(int search_task_id, bool intermediate);
+ Q_SIGNAL void Error(int search_task_id);
+ Q_SIGNAL void Cancelled(int search_task_id);
+ Q_SIGNAL void SearchFinished(int search_task_id, bool success);
+
+protected:
+ Q_SLOT virtual void ReplyFinished(QNetworkReply *) = 0;
+ Q_SLOT virtual void DownloadProgress(qint64, qint64);
+ Q_SLOT virtual void NetworkError(QNetworkReply::NetworkError);
+
+private:
+ void FixLocation(QUrl *url);
+
+private:
+ QNetworkAccessManager *_network;
+ static QMutex _next_search_task_id_mutex;
+ static int _next_search_task_id;
+ int _search_task_id;
+ int _start;
+ QString _location;
+};
+
+#endif // ABSTRACTSEARCHCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "gpsclient.h"
+
+#ifdef QT_MOBILITY_LOCATION
+#include <QGeoPositionInfoSource>
+#endif
+
+#ifdef LIBLOCATION
+#include <QTimer>
+#endif
+
+#include <QUrl>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QMutexLocker>
+#include <iostream>
+
+#ifdef LIBLOCATION
+static void changed(LocationGPSDevice *device, gpointer userdata)
+{
+ Q_UNUSED(device);
+ ((GpsClient *) userdata)->GpsChanged();
+}
+
+static void connected(LocationGPSDevice *device, gpointer userdata)
+{
+ Q_UNUSED(device);
+ ((GpsClient *) userdata)->GpsConnected();
+}
+
+static void disconnected(LocationGPSDevice *device, gpointer userdata)
+{
+ Q_UNUSED(device);
+ ((GpsClient *) userdata)->GpsDisconnected();
+}
+#endif
+
+GpsClient::GpsClient()
+ :
+#ifdef QT_MOBILITY_LOCATION
+ _geo_position_info_source(QGeoPositionInfoSource::createDefaultSource(this)),
+#endif
+#ifdef LIBLOCATION
+ _location_gpsd_control(0),
+ _location_gps_device(0),
+ _time_out_timer(new QTimer(this)),
+#endif
+ _network(new QNetworkAccessManager(this)),
+ _search_task_id(INVALID_SEARCH_TASK_ID)
+{
+ {
+ QMutexLocker locker(&_next_search_task_id_mutex);
+ _search_task_id = _next_search_task_id++;
+ }
+#ifdef QT_MOBILITY_LOCATION
+ connect(_geo_position_info_source, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(GeoPositionUpdated(const QGeoPositionInfo &)));
+ connect(_geo_position_info_source, SIGNAL(updateTimeout()), this, SLOT(GeoPositionTimedOut()));
+#endif
+#ifdef LIBLOCATION
+ connect(_time_out_timer, SIGNAL(timeout()), this, SLOT(GpsTimedOut()));
+#endif
+ connect(_network, SIGNAL(finished(QNetworkReply*)), this, SLOT(ReplyFinished(QNetworkReply*)));
+}
+
+GpsClient::~GpsClient()
+{
+#ifdef LIBLOCATION
+ if (_location_gps_device != 0)
+ g_object_unref(_location_gps_device);
+ if (_location_gpsd_control != 0)
+ location_gpsd_control_stop(_location_gpsd_control);
+#endif
+}
+
+void GpsClient::SearchLocation()
+{
+ _semaphore.Activate(GetSearchTaskId());
+#ifdef QT_MOBILITY_LOCATION
+ _geo_position_info_source->requestUpdate(30 * 1000);
+ emit SearchStarted(GetSearchTaskId());
+#elif defined(LIBLOCATION)
+ _location_gpsd_control = location_gpsd_control_get_default();
+ if (_location_gpsd_control != 0) {
+ location_gpsd_control_start(_location_gpsd_control);
+ }
+ emit SearchStarted(GetSearchTaskId());
+ _location_gps_device = (LocationGPSDevice *) g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
+ if (_location_gps_device != 0) {
+ location_gps_device_reset_last_known(_location_gps_device);
+ g_signal_connect(_location_gps_device, "changed", G_CALLBACK(changed), this);
+ g_signal_connect(_location_gps_device, "connected", G_CALLBACK(connected), this);
+ g_signal_connect(_location_gps_device, "disconnected", G_CALLBACK(disconnected), this);
+ }
+ _time_out_timer->start(30 * 1000);
+#else
+ emit SearchStarted(GetSearchTaskId());
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+#endif
+}
+
+void GpsClient::CancelAllRunningSearchs()
+{
+ _semaphore.CancelAll();
+}
+
+#ifdef QT_MOBILITY_LOCATION
+void GpsClient::GeoPositionUpdated(const QGeoPositionInfo &geo_position_info)
+{
+ if (geo_position_info.coordinate().isValid()) {
+ //std::cout << "longitude " << geo_position_info.coordinate().longitude()
+ // << ", latitude " << geo_position_info.coordinate().latitude()
+ // << ", altitude " << geo_position_info.coordinate().altitude()
+ // << std::endl;
+ SearchTown(QString("%1").arg(geo_position_info.coordinate().longitude()),
+ QString("%1").arg(geo_position_info.coordinate().latitude()));
+ emit SearchForTownStarted(GetSearchTaskId());
+ } else {
+ //std::cout << "invalid coordinate received" << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ }
+}
+
+void GpsClient::GeoPositionTimedOut()
+{
+ //std::cout << "time-out" << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+}
+#endif
+
+#ifdef LIBLOCATION
+void GpsClient::GpsConnected()
+{
+ //std::cout << "connected" << std::endl;
+}
+
+void GpsClient::GpsChanged()
+{
+ if (_location_gps_device->status == LOCATION_GPS_DEVICE_STATUS_FIX
+ && _location_gps_device->fix != 0
+ && (_location_gps_device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET) != 0)
+ {
+ //std::cout << "longitude " << _location_gps_device->fix->longitude
+ // << ", latitude " << _location_gps_device->fix->latitude
+ // << ", altitude " << _location_gps_device->fix->altitude
+ // << ", eph " << _location_gps_device->fix->eph
+ // << std::endl;
+ if (_location_gps_device->fix->eph != LOCATION_GPS_DEVICE_NAN
+ && _location_gps_device->fix->eph <= (20 * 1000 * 100)) // 20km
+ {
+ SearchTown(QString("%1").arg(_location_gps_device->fix->longitude),
+ QString("%1").arg(_location_gps_device->fix->latitude));
+ emit SearchForTownStarted(GetSearchTaskId());
+ } else {
+ //std::cout << "waiting for better accuracy" << std::endl;
+ }
+ } else {
+ //std::cout << "waiting for location" << std::endl;
+ }
+}
+
+void GpsClient::GpsDisconnected()
+{
+ //std::cout << "disconnected" << std::endl;
+}
+
+void GpsClient::GpsTimedOut()
+{
+ //std::cout << "time-out" << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+}
+#endif
+
+void GpsClient::SearchTown(const QString &longitude, const QString &latitude)
+{
+ // TODO: try to fetch a unique city name, at least with country code.
+ // http://code.google.com/intl/en/apis/maps/documentation/geocoding/index.html#ReverseGeocoding
+ QUrl url("http://maps.google.com/maps/geo");
+ url.addEncodedQueryItem("q", QUrl::toPercentEncoding(latitude + "," + longitude));
+ url.addEncodedQueryItem("output", QUrl::toPercentEncoding("xml"));
+ _network->get(QNetworkRequest(url));
+}
+
+void GpsClient::ReplyFinished(QNetworkReply *network_reply)
+{
+ if (!network_reply->error()) {
+ QString data = QString::fromUtf8(network_reply->readAll());
+ int start = data.indexOf("<LocalityName>");
+ if (start >= 0) {
+ int end = data.indexOf("</LocalityName>", start);
+ QString town = data.mid(start + 14, end - start - 14);
+ if (!town.isEmpty()) {
+ //std::cout << "Found town " << qPrintable(town) << std::endl;
+ emit TownUpdate(GetSearchTaskId(), town);
+ emit SearchFinished(GetSearchTaskId(), true);
+ deleteLater();
+ } else {
+ //std::cout << "No town found in " << qPrintable(data) << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ }
+ } else {
+ //std::cout << "No <LocalityName> found in " << qPrintable(data) << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ }
+ }
+ network_reply->deleteLater();
+}
+
+void GpsClient::NetworkError(QNetworkReply::NetworkError)
+{
+ //std::cout << "Network error" << std::endl;
+ emit SearchError(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+}
+
+QMutex GpsClient::_next_search_task_id_mutex;
+int GpsClient::_next_search_task_id = 1;
+SearchClientSemaphore GpsClient::_semaphore;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef GPSCLIENT_H
+#define GPSCLIENT_H
+
+#include "searchclientsemaphore.h"
+
+#include <QObject>
+#include <QMutex>
+#include <QNetworkReply>
+
+class QNetworkAccessManager;
+
+#ifdef QT_MOBILITY_LOCATION
+#include <qmobilityglobal.h>
+
+QTM_BEGIN_NAMESPACE
+ class QGeoPositionInfo;
+class QGeoPositionInfoSource;
+QTM_END_NAMESPACE;
+
+QTM_USE_NAMESPACE;
+#endif
+
+#ifdef LIBLOCATION
+extern "C" {
+#include <location/location-gps-device.h>
+#include <location/location-gpsd-control.h>
+}
+class QTimer;
+#endif
+
+class GpsClient : public QObject
+{
+ Q_OBJECT
+public:
+ static const int INVALID_SEARCH_TASK_ID = -1;
+
+public:
+ GpsClient();
+ ~GpsClient();
+
+public:
+ int GetSearchTaskId() const { return _search_task_id; }
+
+ void SearchLocation();
+
+ static void CancelAllRunningSearchs();
+
+public:
+ Q_SIGNAL void SearchStarted(int search_task_id);
+ Q_SIGNAL void PositionUpdate(int search_task_id);
+ Q_SIGNAL void SearchForTownStarted(int search_task_id);
+ Q_SIGNAL void TownUpdate(int search_task_id, QString town);
+ Q_SIGNAL void SearchError(int search_task_id);
+ Q_SIGNAL void SearchFinished(int search_task_id, bool success);
+
+private:
+#ifdef QT_MOBILITY_LOCATION
+ Q_SLOT void GeoPositionUpdated(const QGeoPositionInfo &);
+ Q_SLOT void GeoPositionTimedOut();
+#endif
+
+#ifdef LIBLOCATION
+public:
+ void GpsConnected();
+ void GpsChanged();
+ void GpsDisconnected();
+ Q_SLOT void GpsTimedOut();
+#endif
+
+private:
+ void SearchTown(const QString &longitude, const QString &latitude);
+ Q_SLOT void ReplyFinished(QNetworkReply *);
+ Q_SLOT void NetworkError(QNetworkReply::NetworkError);
+
+private:
+#ifdef QT_MOBILITY_LOCATION
+ QGeoPositionInfoSource *_geo_position_info_source;
+#endif
+
+#ifdef LIBLOCATION
+ LocationGPSDControl *_location_gpsd_control;
+ LocationGPSDevice *_location_gps_device;
+ QTimer *_time_out_timer;
+#endif
+
+ QNetworkAccessManager *_network;
+ static QMutex _next_search_task_id_mutex;
+ static int _next_search_task_id;
+ int _search_task_id;
+ static SearchClientSemaphore _semaphore;
+};
+
+#endif // GPSCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "movieschedulesearchclient.h"
+
+#include "data/cinemaschedule.h"
+#include "data/cinema.h"
+#include "data/scheduleentry.h"
+#include "data/movie.h"
+#include "utils/timeutils.h"
+#include "utils/assertedlocker.h"
+
+#include <QXmlStreamReader>
+#include <QRegExp>
+#include <QUrl>
+#include <iostream>
+
+MovieScheduleSearchClient::MovieScheduleSearchClient(CinemaSchedule *cinema_schedule, QObject *parent)
+ : AbstractSearchClient(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+void MovieScheduleSearchClient::SearchSchedule(const MovieKey &movie_key, const QString &url)
+{
+ setObjectName(QString("MovieScheduleSearchClient:%1").arg(movie_key.GetName()));
+ _semaphore.Activate(GetSearchTaskId());
+ _movie_key = movie_key;
+ _date = QDate::currentDate();
+ _url = QUrl::fromEncoded(QString("http://www.google.com" + url).toAscii(), QUrl::TolerantMode);
+ _dates_seen.clear();
+ _dates_seen.insert("0");
+ _date_urls.clear();
+ Search(0);
+}
+
+void MovieScheduleSearchClient::CancelAllRunningSearchs()
+{
+ _semaphore.CancelAll();
+}
+
+void MovieScheduleSearchClient::Search(int start)
+{
+ AbstractSearchClient::Search(_url, start);
+}
+
+void MovieScheduleSearchClient::SearchNextDate()
+{
+ if (_date_urls.isEmpty()) {
+ return;
+ }
+ QPair<QUrl, QDate> pair = _date_urls.dequeue();
+ _date = pair.second;
+ _url = pair.first;
+ Search(0);
+}
+
+enum State {
+ PARSE_HTML,
+ PARSE_DATE_LINK,
+ PARSE_THEATER_DIV,
+ PARSE_THEATER_LINK,
+ PARSE_PHONE_LINK,
+ PARSE_LINK,
+ PARSE_BR,
+ PARSE_SPAN,
+};
+
+void MovieScheduleSearchClient::ReplyFinished(QNetworkReply *reply)
+{
+ //std::cout << "REPLY" << std::endl;
+ //std::cout << reply->readAll().data() << std::endl;
+ QXmlStreamReader xml(reply);
+ State state = PARSE_HTML;
+ int found = 0;
+ QString theater_name;
+ QString theater_address;
+ QString theater_phone;
+ QList<QTime> schedule;
+ QRegExp time_pattern("\\d+:\\d+([aApP][mM])*");
+ while (!xml.atEnd()) {
+ QXmlStreamReader::TokenType token = xml.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ QString attr_href = xml.attributes().value("href").toString();
+ //std::cout << qPrintable(xml.name().toString()) << ", class " << qPrintable(attr_class) << ", href " << qPrintable(attr_href) << std::endl;
+ if (state == PARSE_HTML && xml.name() == "a" && attr_href.startsWith("/m/movies")) {
+ QUrl url = QUrl::fromEncoded(QString("http://www.google.com" + attr_href).toAscii(), QUrl::TolerantMode);
+ //std::cout << "LINK " << qPrintable(attr_href) << std::endl;
+ if (url.hasQueryItem("date")) {
+ QString v = url.queryItemValue("date");
+ std::cout << "FOUND Date Link " << qPrintable(v) << " from " << qPrintable(url.toString()) << std::endl;
+ if (!_dates_seen.contains(v)) {
+ // TODO replace location with user selected location (Google simplifies to much)
+ _dates_seen.insert(v);
+ _date_urls.append(qMakePair(url, QDate::currentDate().addDays(v.toInt())));
+ }
+ state = PARSE_DATE_LINK;
+ } else if (url.hasQueryItem("tid")) {
+ theater_name = "";
+ theater_address = "";
+ theater_phone = "";
+ schedule.clear();
+ state = PARSE_THEATER_LINK;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "a") {
+ if (attr_href.startsWith("wtai:")) {
+ state = PARSE_PHONE_LINK;
+ } else {
+ state = PARSE_LINK;
+ }
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "br") {
+ state = PARSE_BR;
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "span") {
+ state = PARSE_SPAN;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (state == PARSE_DATE_LINK) {
+ state = PARSE_HTML;
+ } else if (state == PARSE_THEATER_LINK) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_BR) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_SPAN) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_LINK) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_PHONE_LINK) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_THEATER_DIV) {
+ state = PARSE_HTML;
+ if (!theater_name.isEmpty()) {
+ ++found;
+ if (!schedule.isEmpty()) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ if (!_semaphore.IsActive(GetSearchTaskId())) {
+ break;
+ }
+ const Movie *movie = _cinema_schedule->FindMovie(_movie_key);
+ if (movie != 0) {
+ //std::cout << "ADD SCHEDULE " << qPrintable(theater_name) << ", " << qPrintable(theater_address) << std::endl;
+ CinemaKey key(theater_name, theater_address);
+ Cinema *cinema = _cinema_schedule->FindCinema(key);
+ if (cinema == 0) {
+ cinema = _cinema_schedule->AddCinema(key);
+ }
+ if (!theater_phone.isEmpty()) {
+ cinema->SetTelephone(theater_phone);
+ }
+ Q_FOREACH(const QTime time, schedule) {
+ _cinema_schedule->AddSchedule(cinema, movie, time, _date);
+ }
+ }
+ }
+ }
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ if (state == PARSE_THEATER_LINK) {
+ //std::cout << "name " << qPrintable(xml.text().toString()) << std::endl;
+ theater_name = xml.text().toString();
+ } else if (state == PARSE_PHONE_LINK) {
+ //std::cout << "phone " << qPrintable(xml.text().toString()) << std::endl;
+ theater_phone = xml.text().toString();
+ } else if (state == PARSE_SPAN) {
+ QString t = xml.text().toString();
+ int i = 0;
+ bool found = false;
+ while ((i = time_pattern.indexIn(t, i)) != -1) {
+ int length = time_pattern.matchedLength();
+ //std::cout << "time " << qPrintable(t.mid(i, length)) << std::endl;
+ QTime time = TimeUtils::FromTimeString(t.mid(i, length));
+ if (time.isValid()) {
+ schedule.append(time);
+ } else {
+ std::cout << "ERROR: time " << qPrintable(t.mid(i, length)) << " is invalid." << std::endl;
+ }
+ i += length;
+ found = true;
+ }
+ if (!found) {
+ //std::cout << "address " << qPrintable(t) << std::endl;
+ theater_address = t;
+ }
+ }
+ }
+ }
+ if (xml.hasError()) {
+ emit SearchFinished(GetSearchTaskId(), false);
+ std::cout << "xml error (" << xml.lineNumber() << "/" << xml.columnNumber() << "): " << qPrintable(xml.errorString()) << std::endl;
+ emit Error(GetSearchTaskId());
+ deleteLater();
+ } else if (!_semaphore.IsActive(GetSearchTaskId())) {
+ emit Cancelled(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ } else {
+ if (found > 0) {
+ emit Reply(GetSearchTaskId(), true);
+ Search(GetStartIndex() + found);
+ } else {
+ if (!_date_urls.isEmpty()) {
+ SearchNextDate();
+ } else {
+ emit Reply(GetSearchTaskId(), false);
+ emit SearchFinished(GetSearchTaskId(), true);
+ deleteLater();
+ }
+ }
+ }
+ reply->deleteLater();
+ //std::cout << "REPLY FINISHED" << std::endl;
+}
+
+SearchClientSemaphore MovieScheduleSearchClient::_semaphore;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIESCHEDULESEARCHCLIENT_H
+#define MOVIESCHEDULESEARCHCLIENT_H
+
+#include "abstractsearchclient.h"
+#include "searchclientsemaphore.h"
+#include "data/moviekey.h"
+
+#include <QUrl>
+#include <QQueue>
+#include <QSet>
+#include <QPair>
+#include <QDate>
+
+class CinemaSchedule;
+class Movie;
+
+class MovieScheduleSearchClient : public AbstractSearchClient
+{
+ Q_OBJECT
+public:
+ explicit MovieScheduleSearchClient(CinemaSchedule *cinema_schedule, QObject *parent = 0);
+
+ void SearchSchedule(const MovieKey &movie_key, const QString &url);
+
+ static void CancelAllRunningSearchs();
+
+private:
+ void Search(int start);
+ void SearchNextDate();
+ Q_SLOT virtual void ReplyFinished(QNetworkReply *);
+
+private:
+ CinemaSchedule *_cinema_schedule;
+ MovieKey _movie_key;
+ QDate _date;
+ QUrl _url;
+ QSet<QString> _dates_seen;
+ QQueue<QPair<QUrl, QDate> > _date_urls;
+ static SearchClientSemaphore _semaphore;
+};
+
+#endif // MOVIESCHEDULESEARCHCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviesearchclient.h"
+
+#include "data/cinemaschedule.h"
+#include "data/movie.h"
+#include "data/moviekey.h"
+#include "utils/assertedlocker.h"
+
+#include <QXmlStreamReader>
+#include <QRegExp>
+#include <iostream>
+
+MovieSearchClient::MovieSearchClient(CinemaSchedule *cinema_schedule, QObject *parent)
+ : AbstractSearchClient(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+void MovieSearchClient::SearchMovie(const QString &town)
+{
+ _semaphore.Activate(GetSearchTaskId());
+ setObjectName(QString("MovieSearchClient:%1").arg(town));
+ _town = town;
+ Search(0);
+}
+
+void MovieSearchClient::CancelAllRunningSearchs()
+{
+ _semaphore.CancelAll();
+}
+
+void MovieSearchClient::Search(int start)
+{
+ QUrl url("http://www.google.com/m/movies");
+ url.addQueryItem("loc", _town);
+ url.addQueryItem("sort", QString::number(1));
+ AbstractSearchClient::Search(url, start);
+}
+
+enum State {
+ PARSE_HTML,
+ PARSE_MOVIE_LINK,
+ PARSE_EXPECT_DIV1,
+ PARSE_EXPECT_DIV2, PARSE_DIV2,
+ PARSE_SPAN, PARSE_RATING, PARSE_TRAILER
+};
+
+void MovieSearchClient::ReplyFinished(QNetworkReply *reply)
+{
+ //std::cout << qPrintable(QString(reply->readAll())) << std::endl;
+ QXmlStreamReader xml(reply);
+ State state = PARSE_HTML;
+ int found = 0;
+ QString movie_name;
+ QVector<QString> movie_spans;
+ double movie_rating = -1.0;
+ QString movie_theaters_url;
+ QRegExp duration_pattern("((\\d+)hr )?(\\d+)min");
+ QRegExp reviews_pattern("\\d+ review(s)?");
+ while (!xml.atEnd()) {
+ QXmlStreamReader::TokenType token = xml.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ QString attr_class = xml.attributes().value("class").toString();
+ QString attr_href = xml.attributes().value("href").toString();
+ //std::cout << "tag = " << qPrintable(xml.name().toString()) << ", class = " << qPrintable(attr_class) << ", href = " << qPrintable(attr_href) << std::endl;
+ if (state == PARSE_HTML && xml.name() == "a" && attr_href.startsWith("/m/movies")) {
+ QUrl url = QUrl::fromEncoded(QString("http://www.google.com" + attr_href).toAscii(), QUrl::TolerantMode);
+ //std::cout << "LINK " << qPrintable(attr_href) << std::endl;
+ if (url.hasQueryItem("mid")) {
+ movie_name = "";
+ movie_spans.clear();
+ movie_rating = -1.0;
+ movie_theaters_url = attr_href;
+ state = PARSE_MOVIE_LINK;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (state == PARSE_EXPECT_DIV2 && xml.name() == "div") {
+ state = PARSE_DIV2;
+ } else if (state == PARSE_DIV2 && xml.name() == "span" && attr_class.isEmpty()) {
+ movie_spans.append("");
+ state = PARSE_SPAN;
+ } else if (state == PARSE_DIV2 && xml.name() == "img") {
+ movie_rating = (double) xml.attributes().value("src").at(41).digitValue() / 10.0;
+ //std::cout << "rating: " << movie_rating << std::endl;
+ state = PARSE_RATING;
+ } else if (state == PARSE_DIV2 && xml.name() == "a") {
+ state = PARSE_TRAILER;
+ } else if (state != PARSE_HTML) {
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (state == PARSE_MOVIE_LINK) {
+ state = PARSE_EXPECT_DIV1;
+ } else if (state == PARSE_EXPECT_DIV1) {
+ state = PARSE_EXPECT_DIV2;
+ } else if (state == PARSE_EXPECT_DIV2) {
+ state = PARSE_HTML;
+ } else if (state == PARSE_SPAN) {
+ state = PARSE_DIV2;
+ } else if (state == PARSE_RATING) {
+ state = PARSE_DIV2;
+ } else if (state == PARSE_TRAILER) {
+ state = PARSE_DIV2;
+ } else if (state == PARSE_DIV2) {
+ if (!movie_name.isEmpty()) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ if (!_semaphore.IsActive(GetSearchTaskId())) {
+ break;
+ }
+ //std::cout << "ADD MOVIE " << qPrintable(movie_name) << std::endl;
+ ++found;
+ MovieKey key(movie_name);
+ Movie *movie = _cinema_schedule->FindMovie(key);
+ if (movie == 0) {
+ movie = _cinema_schedule->AddMovie(key);
+ }
+ if (!movie_theaters_url.isEmpty()) {
+ movie->SetTheatersUrl(movie_theaters_url);
+ }
+ if (movie_rating >= 0.0) {
+ movie->SetRate(movie_rating);
+ }
+ Q_FOREACH (QString s, movie_spans) {
+ if (duration_pattern.exactMatch(s)) {
+ QString hours = duration_pattern.cap(2);
+ QString minutes = duration_pattern.cap(3);
+ //std::cout << "hours = " << qPrintable(hours) << ", minutes = " << qPrintable(minutes) << ",0: " << qPrintable(duration_pattern.cap(0)) << ", 1: " << qPrintable(duration_pattern.cap(1)) << std::endl;
+ movie->SetDuration(QTime(hours.toInt(), minutes.toInt()));
+ } else if (reviews_pattern.exactMatch(s)) {
+ // Ignore number of reviews
+ } else {
+ movie->SetComment(s);
+ }
+ }
+ }
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ if (state == PARSE_MOVIE_LINK) {
+ //std::cout << "movie: " << qPrintable(xml.text().toString()) << std::endl;
+ movie_name = xml.text().toString();
+ } else if (state == PARSE_SPAN) {
+ int i = movie_spans.size()-1;
+ if (movie_spans[i].isEmpty()) {
+ movie_spans[i] = xml.text().toString();
+ } else if (!xml.text().isEmpty()) {
+ movie_spans[i] += " ";
+ movie_spans[i] += xml.text().toString();
+ }
+ //std::cout << " span: " << qPrintable(movie_spans[i]) << std::endl;
+ }
+ }
+ }
+ if (xml.hasError()) {
+ std::cout << "xml error (" << xml.lineNumber() << "/" << xml.columnNumber() << "): " << qPrintable(xml.errorString()) << std::endl;
+ emit Error(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ } else if (!_semaphore.IsActive(GetSearchTaskId())) {
+ emit Cancelled(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ } else {
+ if (found > 0) {
+ emit Reply(GetSearchTaskId(), true);
+ Search(GetStartIndex() + found);
+ } else {
+ emit Reply(GetSearchTaskId(), false);
+ emit SearchFinished(GetSearchTaskId(), true);
+ deleteLater();
+ }
+ }
+ reply->deleteLater();
+}
+
+SearchClientSemaphore MovieSearchClient::_semaphore;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIESEARCHCLIENT_H
+#define MOVIESEARCHCLIENT_H
+
+#include "abstractsearchclient.h"
+#include "searchclientsemaphore.h"
+
+class CinemaSchedule;
+
+class MovieSearchClient : public AbstractSearchClient
+{
+ Q_OBJECT
+public:
+ explicit MovieSearchClient(CinemaSchedule *cinema_schedule, QObject *parent = 0);
+
+ void SearchMovie(const QString &town);
+
+ static void CancelAllRunningSearchs();
+
+private:
+ void Search(int start);
+ Q_SLOT virtual void ReplyFinished(QNetworkReply *);
+
+private:
+ CinemaSchedule *_cinema_schedule;
+ QString _town;
+ static SearchClientSemaphore _semaphore;
+};
+
+#endif // MOVIESEARCHCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "searchclientsemaphore.h"
+
+static const int INVALID_ID = -1;
+
+SearchClientSemaphore::SearchClientSemaphore()
+ : _mutex(),
+ _active_search_task_id(INVALID_ID)
+{
+}
+
+void SearchClientSemaphore::Activate(int search_task_id)
+{
+ _active_search_task_id = search_task_id;
+}
+
+bool SearchClientSemaphore::IsActive(int search_task_id)
+{
+ return _active_search_task_id == search_task_id;
+}
+
+void SearchClientSemaphore::CancelAll()
+{
+ _active_search_task_id = INVALID_ID;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SEARCHCLIENTSEMAPHORE_H
+#define SEARCHCLIENTSEMAPHORE_H
+
+#include <QMutex>
+
+class SearchClientSemaphore
+{
+public:
+ SearchClientSemaphore();
+
+ void Activate(int search_task_id);
+
+ bool IsActive(int search_task_id);
+
+ void CancelAll();
+
+private:
+ QMutex _mutex;
+ int _active_search_task_id;
+};
+
+#endif // SEARCHCLIENTSEMAPHORE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theaterschedulesearchclient.h"
+
+#include "data/cinemaschedule.h"
+#include "data/cinema.h"
+#include "data/scheduleentry.h"
+#include "data/movie.h"
+#include "utils/timeutils.h"
+#include "utils/assertedlocker.h"
+
+#include <QXmlStreamReader>
+#include <QRegExp>
+#include <iostream>
+
+TheaterScheduleSearchClient::TheaterScheduleSearchClient(CinemaSchedule *cinema_schedule, QObject *parent)
+ : AbstractSearchClient(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+void TheaterScheduleSearchClient::SearchSchedule(const CinemaKey &cinema_key, const QString &url)
+{
+ setObjectName(QString("TheaterScheduleSearchClient:%1").arg(cinema_key.GetName()));
+ _semaphore.Activate(GetSearchTaskId());
+ _cinema_key = cinema_key;
+ _date = QDate::currentDate();
+ _url = QUrl::fromEncoded(QString("http://www.google.com" + url).toAscii(), QUrl::TolerantMode);
+ _dates_seen.clear();
+ _dates_seen.insert("0");
+ _date_urls.clear();
+ Search(0);
+}
+
+void TheaterScheduleSearchClient::CancelAllRunningSearchs()
+{
+ _semaphore.CancelAll();
+}
+
+void TheaterScheduleSearchClient::Search(int start)
+{
+ AbstractSearchClient::Search(_url, start);
+}
+
+void TheaterScheduleSearchClient::SearchNextDate()
+{
+ if (_date_urls.isEmpty()) {
+ return;
+ }
+ QPair<QUrl, QDate> pair = _date_urls.dequeue();
+ _date = pair.second;
+ _url = pair.first;
+ Search(0);
+}
+
+enum State {
+ PARSE_HTML,
+ PARSE_DATE_LINK,
+ PARSE_MOVIE_DIV,
+ PARSE_MOVIE_DIV1,
+ PARSE_MOVIE_LINK,
+ PARSE_MOVIE_EXPECT_DIV2,
+ PARSE_MOVIE_DIV2,
+ PARSE_MOVIE_SPAN,
+ PARSE_MOVIE_TRAILER_LINK,
+ PARSE_MOVIE_RATING,
+ PARSE_MOVIE_EXPECT_DIV3,
+ PARSE_MOVIE_DIV3,
+ PARSE_MOVIE_TIME,
+};
+
+void TheaterScheduleSearchClient::ReplyFinished(QNetworkReply *reply)
+{
+ State state = PARSE_HTML;
+ int found = 0;
+ QString movie_name;
+ QVector<QString> movie_spans;
+ QString theaters_url;
+ double rating = -1.0;
+ QList<QTime> schedule;
+ QRegExp time_pattern("\\d+:\\d+([aApP][mM])*");
+ QRegExp duration_pattern("((\\d+)hr )?(\\d+)min");
+ QRegExp reviews_pattern("\\d+ review(s)?");
+ QXmlStreamReader xml(reply);
+ while (!xml.atEnd()) {
+ QXmlStreamReader::TokenType token = xml.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ QString attr_href = xml.attributes().value("href").toString();
+ //std::cout << "name: " << qPrintable(xml.name().toString()) << ", href " << qPrintable(attr_href) << std::endl;
+ if (state == PARSE_HTML && xml.name() == "a" && attr_href.startsWith("/m/movies")) {
+ QUrl url = QUrl::fromEncoded(QString("http://www.google.com" + attr_href).toAscii(), QUrl::TolerantMode);
+ //std::cout << "LINK " << qPrintable(attr_href) << std::endl;
+ if (url.hasQueryItem("date")) {
+ QString v = url.queryItemValue("date");
+ //std::cout << "FOUND Date Link " << qPrintable(v) << " from " << qPrintable(url.toString()) << std::endl;
+ if (!_dates_seen.contains(v)) {
+ // TODO replace location with user selected location (Google simplifies to much)
+ _dates_seen.insert(v);
+ _date_urls.append(qMakePair(url, QDate::currentDate().addDays(v.toInt())));
+ }
+ state = PARSE_DATE_LINK;
+ } else if (url.hasQueryItem("mid")) {
+ //std::cout << "FOUND Movie Link" << std::endl;
+ movie_name = "";
+ movie_spans.clear();
+ theaters_url = attr_href;
+ rating = -1.0;
+ schedule.clear();
+ state = PARSE_MOVIE_LINK;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (state == PARSE_MOVIE_EXPECT_DIV2 && xml.name() == "div") {
+ //std::cout << "PARSE_MOVIE_DIV2" << std::endl;
+ state = PARSE_MOVIE_DIV2;
+ } else if (state == PARSE_MOVIE_DIV2 && xml.name() == "span") {
+ movie_spans.append("");
+ //std::cout << "PARSE_MOVIE_SPAN" << std::endl;
+ state = PARSE_MOVIE_SPAN;
+ } else if (state == PARSE_MOVIE_DIV2 && xml.name() == "a") {
+ state = PARSE_MOVIE_TRAILER_LINK;
+ } else if (state == PARSE_MOVIE_DIV2 && xml.name() == "img") {
+ rating = (double) xml.attributes().value("src").at(41).digitValue() / 10.0;
+ //std::cout << "rate: " << rate << std::endl;
+ state = PARSE_MOVIE_RATING;
+ } else if (state == PARSE_MOVIE_EXPECT_DIV3 && xml.name() == "div") {
+ //std::cout << "PARSE_MOVIE_DIV3" << std::endl;
+ state = PARSE_MOVIE_DIV3;
+ } else if (state == PARSE_MOVIE_DIV3 && xml.name() == "span") {
+ //std::cout << "PARSE_MOVIE_TIME" << std::endl;
+ state = PARSE_MOVIE_TIME;
+ } else {
+ //std::cout << "TAG " << qPrintable(xml.name().toString()) << std::endl;
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (state == PARSE_DATE_LINK) {
+ state = PARSE_HTML;
+ } else if (state == PARSE_MOVIE_LINK) {
+ state = PARSE_MOVIE_DIV1;
+ } else if (state == PARSE_MOVIE_DIV1) {
+ state = PARSE_MOVIE_EXPECT_DIV2;
+ } else if (state == PARSE_MOVIE_SPAN) {
+ state = PARSE_MOVIE_DIV2;
+ } else if (state == PARSE_MOVIE_TRAILER_LINK) {
+ state = PARSE_MOVIE_DIV2;
+ } else if (state == PARSE_MOVIE_RATING) {
+ state = PARSE_MOVIE_DIV2;
+ } else if (state == PARSE_MOVIE_DIV2) {
+ state = PARSE_MOVIE_EXPECT_DIV3;
+ } else if (state == PARSE_MOVIE_TIME) {
+ state = PARSE_MOVIE_DIV3;
+ } else if (state == PARSE_MOVIE_DIV3) {
+ state = PARSE_MOVIE_DIV;
+ } else if (state == PARSE_MOVIE_DIV) {
+ if (!movie_name.isEmpty()) {
+ ++found;
+ if (!schedule.isEmpty()) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ if (!_semaphore.IsActive(GetSearchTaskId())) {
+ break;
+ }
+ const Cinema *cinema = _cinema_schedule->FindCinema(_cinema_key);
+ if (cinema != 0) {
+ //std::cout << "ADD SCHEDULE " << qPrintable(movie_name) << ", " << qPrintable(duration)
+ // << ", " << qPrintable(age) << ", " << rate << std::endl;
+ MovieKey key(movie_name);
+ Movie *movie = _cinema_schedule->FindMovie(key);
+ if (movie == 0) {
+ movie = _cinema_schedule->AddMovie(key);
+ }
+ if (!theaters_url.isEmpty()) {
+ movie->SetTheatersUrl(theaters_url);
+ }
+ if (rating >= 0.0) {
+ movie->SetRate(rating);
+ }
+ Q_FOREACH (QString s, movie_spans) {
+ if (duration_pattern.exactMatch(s)) {
+ QString hours = duration_pattern.cap(2);
+ QString minutes = duration_pattern.cap(3);
+ //std::cout << "hours = " << qPrintable(hours) << ", minutes = " << qPrintable(minutes) << ",0: " << qPrintable(duration_pattern.cap(0)) << ", 1: " << qPrintable(duration_pattern.cap(1)) << std::endl;
+ movie->SetDuration(QTime(hours.toInt(), minutes.toInt()));
+ } else if (reviews_pattern.exactMatch(s)) {
+ // Ignore number of reviews
+ } else {
+ movie->SetComment(s);
+ }
+ }
+ Q_FOREACH(const QTime time, schedule) {
+ _cinema_schedule->AddSchedule(cinema, movie, time, _date);
+ }
+ }
+ }
+ }
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ if (state == PARSE_MOVIE_LINK) {
+ //std::cout << "MOVIE " << qPrintable(xml.text().toString()) << std::endl;
+ movie_name = xml.text().toString();
+ } else if (state == PARSE_MOVIE_SPAN) {
+ int i = movie_spans.size()-1;
+ if (movie_spans[i].isEmpty()) {
+ movie_spans[i] = xml.text().toString();
+ } else if (!xml.text().isEmpty()) {
+ movie_spans[i] += " ";
+ movie_spans[i] += xml.text().toString();
+ }
+ //std::cout << " span: " << qPrintable(movie_spans[i]) << std::endl;
+ } else if (state == PARSE_MOVIE_TIME) {
+ QString t = xml.text().toString();
+ int i = 0;
+ while ((i = time_pattern.indexIn(t, i)) != -1) {
+ int length = time_pattern.matchedLength();
+ QTime time = TimeUtils::FromTimeString(t.mid(i, length));
+ if (time.isValid()) {
+ schedule.append(time);
+ } else {
+ //std::cout << "ERROR: time " << qPrintable(t.mid(i, length)) << " is invalid." << std::endl;
+ }
+ i += length;
+ }
+ }
+ }
+ }
+ if (xml.hasError()) {
+ emit SearchFinished(GetSearchTaskId(), false);
+ std::cout << "xml error (" << xml.lineNumber() << "/" << xml.columnNumber() << "): " << qPrintable(xml.errorString()) << std::endl;
+ emit Error(GetSearchTaskId());
+ deleteLater();
+ } else if (!_semaphore.IsActive(GetSearchTaskId())) {
+ emit Cancelled(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ } else {
+ // all movies are listed on one page
+ // no repetition of search with start parameter
+ if (!_date_urls.isEmpty()) {
+ emit Reply(GetSearchTaskId(), true);
+ SearchNextDate();
+ } else {
+ emit Reply(GetSearchTaskId(), false);
+ emit SearchFinished(GetSearchTaskId(), true);
+ deleteLater();
+ }
+ }
+ reply->deleteLater();
+}
+
+SearchClientSemaphore TheaterScheduleSearchClient::_semaphore;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERSCHEDULESEARCHCLIENT_H
+#define THEATERSCHEDULESEARCHCLIENT_H
+
+#include "abstractsearchclient.h"
+#include "searchclientsemaphore.h"
+#include "data/cinemakey.h"
+
+#include <QDate>
+#include <QUrl>
+#include <QSet>
+#include <QQueue>
+#include <QPair>
+
+class CinemaSchedule;
+
+class TheaterScheduleSearchClient : public AbstractSearchClient
+{
+ Q_OBJECT
+public:
+ explicit TheaterScheduleSearchClient(CinemaSchedule *cinema_schedule, QObject *parent = 0);
+
+ void SearchSchedule(const CinemaKey &cinema_key, const QString &url);
+
+ static void CancelAllRunningSearchs();
+
+private:
+ void Search(int start);
+ void SearchNextDate();
+ Q_SLOT virtual void ReplyFinished(QNetworkReply *);
+
+private:
+ CinemaSchedule *_cinema_schedule;
+ CinemaKey _cinema_key;
+ QDate _date;
+ QUrl _url;
+ QSet<QString> _dates_seen;
+ QQueue<QPair<QUrl, QDate> > _date_urls;
+ static SearchClientSemaphore _semaphore;
+};
+
+#endif // THEATERSCHEDULESEARCHCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theatersearchclient.h"
+
+#include "data/cinemakey.h"
+#include "data/cinema.h"
+#include "data/cinemaschedule.h"
+#include "utils/assertedlocker.h"
+
+#include <QXmlStreamReader>
+#include <iostream>
+
+TheaterSearchClient::TheaterSearchClient(CinemaSchedule *cinema_schedule, QObject *parent)
+ : AbstractSearchClient(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+void TheaterSearchClient::SearchTheater(const QString &town)
+{
+ _semaphore.Activate(GetSearchTaskId());
+ setObjectName(QString("TheaterSearchClient:%1").arg(town));
+ _town = town;
+ Search(0);
+}
+
+void TheaterSearchClient::CancelAllRunningSearchs()
+{
+ _semaphore.CancelAll();
+}
+
+void TheaterSearchClient::Search(int start)
+{
+ QUrl url("http://www.google.com/m/movies");
+ url.addQueryItem("loc", _town);
+ url.addQueryItem("sort", QString::number(0));
+ AbstractSearchClient::Search(url, start);
+}
+
+enum State {
+ PARSE_HTML,
+ PARSE_THEATER_LINK,
+ PARSE_THEATER_DIV,
+ PARSE_THEATER_BR,
+ PARSE_THEATER_SPAN,
+ PARSE_THEATER_PHONE
+};
+
+void TheaterSearchClient::ReplyFinished(QNetworkReply *reply)
+{
+ QXmlStreamReader xml(reply);
+ State state = PARSE_HTML;
+ int found = 0;
+ QString theater_name;
+ QString theater_address;
+ QString theater_movies_url;
+ QString theater_phone;
+ while (!xml.atEnd()) {
+ QXmlStreamReader::TokenType token = xml.readNext();
+ if (token == QXmlStreamReader::StartElement) {
+ QString attr_href = xml.attributes().value("href").toString();
+ //std::cout << "name: " << qPrintable(xml.name().toString()) << ", href: " << qPrintable(attr_href) << std::endl;
+ if (state == PARSE_HTML && xml.name() == "a" && attr_href.startsWith("/m/movies")) {
+ QUrl url = QUrl::fromEncoded(QString("http://www.google.com" + attr_href).toAscii(), QUrl::TolerantMode);
+ //std::cout << "LINK " << qPrintable(attr_href) << std::endl;
+ if (url.hasQueryItem("tid")) {
+ theater_name = "";
+ theater_address = "";
+ theater_movies_url = attr_href;
+ theater_phone = "";
+ state = PARSE_THEATER_LINK;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "br") {
+ state = PARSE_THEATER_BR;
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "span") {
+ state = PARSE_THEATER_SPAN;
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "a" && attr_href.startsWith("wtai:")) {
+ state = PARSE_THEATER_PHONE;
+ } else if (state == PARSE_THEATER_DIV && xml.name() == "a") {
+ state = PARSE_THEATER_BR;
+ } else {
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::EndElement) {
+ if (state == PARSE_THEATER_LINK) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_THEATER_BR) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_THEATER_SPAN) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_THEATER_PHONE) {
+ state = PARSE_THEATER_DIV;
+ } else if (state == PARSE_THEATER_DIV) {
+ if (!theater_name.isEmpty()) {
+ AssertedWriteLocker locker(_cinema_schedule->GetLock());
+ if (!_semaphore.IsActive(GetSearchTaskId())) {
+ break;
+ }
+ ++found;
+ CinemaKey key(theater_name, theater_address);
+ Cinema *cinema = _cinema_schedule->FindCinema(key);
+ if (cinema == 0) {
+ cinema = _cinema_schedule->AddCinema(key);
+ }
+ if (!theater_movies_url.isEmpty()) {
+ cinema->SetMoviesUrl(theater_movies_url);
+ }
+ if (!theater_phone.isEmpty()) {
+ cinema->SetTelephone(theater_phone);
+ }
+ }
+ state = PARSE_HTML;
+ }
+ } else if (token == QXmlStreamReader::Characters) {
+ if (state == PARSE_THEATER_LINK) {
+ theater_name = xml.text().toString();
+ } else if (state == PARSE_THEATER_PHONE) {
+ theater_phone = xml.text().toString();
+ } else if (state == PARSE_THEATER_SPAN) {
+ theater_address = xml.text().toString();
+ }
+ }
+ }
+ if (xml.hasError()) {
+ emit SearchFinished(GetSearchTaskId(), false);
+ std::cout << "xml error (" << xml.lineNumber() << "/" << xml.columnNumber() << "): " << qPrintable(xml.errorString()) << std::endl;
+ emit Error(GetSearchTaskId());
+ deleteLater();
+ } else if (!_semaphore.IsActive(GetSearchTaskId())) {
+ emit Cancelled(GetSearchTaskId());
+ emit SearchFinished(GetSearchTaskId(), false);
+ deleteLater();
+ } else {
+ if (found > 0) {
+ emit Reply(GetSearchTaskId(), true);
+ Search(GetStartIndex() + found);
+ } else {
+ emit Reply(GetSearchTaskId(), false);
+ emit SearchFinished(GetSearchTaskId(), true);
+ deleteLater();
+ }
+ }
+ reply->deleteLater();
+}
+
+SearchClientSemaphore TheaterSearchClient::_semaphore;
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERSEARCHCLIENT_H
+#define THEATERSEARCHCLIENT_H
+
+#include "abstractsearchclient.h"
+#include "searchclientsemaphore.h"
+
+class CinemaSchedule;
+
+class TheaterSearchClient : public AbstractSearchClient
+{
+ Q_OBJECT
+public:
+ explicit TheaterSearchClient(CinemaSchedule *cinema_schedule, QObject *parent = 0);
+
+ void SearchTheater(const QString &town);
+
+ static void CancelAllRunningSearchs();
+
+private:
+ void Search(int start);
+ Q_SLOT virtual void ReplyFinished(QNetworkReply *);
+
+private:
+ CinemaSchedule *_cinema_schedule;
+ QString _town;
+ static SearchClientSemaphore _semaphore;
+};
+
+#endif // THEATERSEARCHCLIENT_H
--- /dev/null
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-03-01T19:21:07
+#
+#-------------------------------------------------
+
+QT += core gui network dbus
+
+CONFIG += link_pkgconfig
+
+maemo5 {
+ QT += maemo5
+ DEFINES += Q_WS_MAEMO_5
+ maemo_sdk {
+ CONFIG += icd2
+ PKGCONFIG += calendar-backend liblocation
+ DEFINES += MAEMO_SDK LIBLOCATION
+ }
+}
+
+mobility {
+ MOBILITY += location
+ DEFINES += QT_MOBILITY
+ !contains(DEFINES, LIBLOCATION) {
+ DEFINES += QT_MOBILITY_LOCATION
+ }
+}
+
+TARGET = movie-schedule
+TEMPLATE = app
+
+INCLUDEPATH += .
+
+SOURCES += \
+ main.cpp \
+ control/actioncontroller.cpp \
+ control/maincontroller.cpp \
+ control/moviecontroller.cpp \
+ control/settingscontroller.cpp \
+ control/theatercontroller.cpp \
+ data/cinema.cpp \
+ data/cinemakey.cpp \
+ data/cinemaschedule.cpp \
+ data/location.cpp \
+ data/movie.cpp \
+ data/moviekey.cpp \
+ data/scheduleentry.cpp \
+ data/scheduleentrykey.cpp \
+ data/settings.cpp \
+ searchclients/abstractsearchclient.cpp \
+ searchclients/movieschedulesearchclient.cpp \
+ searchclients/moviesearchclient.cpp \
+ searchclients/theaterschedulesearchclient.cpp \
+ searchclients/theatersearchclient.cpp \
+ ui/abstractmainwindow.cpp \
+ ui/backgroundlabel.cpp \
+ ui/cinemapainter.cpp \
+ ui/contextdialog.cpp \
+ ui/daypainter.cpp \
+ ui/locationdialog.cpp \
+ ui/mainwindow.cpp \
+ ui/moviedelegate.cpp \
+ ui/moviemodel.cpp \
+ ui/moviepainter.cpp \
+ ui/moviescheduledelegate.cpp \
+ ui/movieschedulemodel.cpp \
+ ui/moviewindow.cpp \
+ ui/ratingprovider.cpp \
+ ui/theaterdelegate.cpp \
+ ui/theatermodel.cpp \
+ ui/theaterscheduledelegate.cpp \
+ ui/theaterschedulemodel.cpp \
+ ui/theaterwindow.cpp \
+ ui/uiutils.cpp \
+ utils/assertedlock.cpp \
+ utils/assertedlocker.cpp \
+ utils/calendar.cpp \
+ utils/timeutils.cpp \
+ movieschedule.cpp \
+ ui/scheduleentryitem.cpp \
+ control/itemmodelsortcontroller.cpp \
+ control/itemmodelsortclient.cpp \
+ control/itemmodelsortproxy.cpp \
+ utils/asynccallclient.cpp \
+ utils/asynccallproxy.cpp \
+ utils/asynccall.cpp \
+ ui/styleutils.cpp \
+ searchclients/gpsclient.cpp \
+ ui/aboutdialog.cpp \
+ searchclients/searchclientsemaphore.cpp \
+ control/locationcontroller.cpp \
+ utils/connectivitymanager.cpp
+
+HEADERS += \
+ control/actioncontroller.h \
+ control/maincontroller.h \
+ control/moviecontroller.h \
+ control/settingscontroller.h \
+ control/theatercontroller.h \
+ data/cinema.h \
+ data/cinemakey.h \
+ data/cinemaschedule.h \
+ data/location.h \
+ data/movie.h \
+ data/moviekey.h \
+ data/scheduleentry.h \
+ data/scheduleentrykey.h \
+ data/settings.h \
+ searchclients/abstractsearchclient.h \
+ searchclients/movieschedulesearchclient.h \
+ searchclients/moviesearchclient.h \
+ searchclients/theaterschedulesearchclient.h \
+ searchclients/theatersearchclient.h \
+ ui/abstractmainwindow.h \
+ ui/backgroundlabel.h \
+ ui/cinemapainter.h \
+ ui/contextdialog.h \
+ ui/daypainter.h \
+ ui/locationdialog.h \
+ ui/mainwindow.h \
+ ui/moviedelegate.h \
+ ui/moviemodel.h \
+ ui/moviepainter.h \
+ ui/moviescheduledelegate.h \
+ ui/movieschedulemodel.h \
+ ui/moviewindow.h \
+ ui/ratingprovider.h \
+ ui/theaterdelegate.h \
+ ui/theatermodel.h \
+ ui/theaterscheduledelegate.h \
+ ui/theaterschedulemodel.h \
+ ui/theaterwindow.h \
+ ui/uiutils.h \
+ utils/assertedlock.h \
+ utils/assertedlocker.h \
+ utils/calendar.h \
+ utils/timeutils.h \
+ utils/connect.h \
+ movieschedule.h \
+ ui/scheduleentryitem.h \
+ control/itemmodelsortcontroller.h \
+ control/itemmodelsortclient.h \
+ control/itemmodelsortproxy.h \
+ utils/asynccallclient.h \
+ utils/asynccallproxy.h \
+ utils/asynccall.h \
+ ui/styleutils.h \
+ searchclients/gpsclient.h \
+ ui/aboutdialog.h \
+ searchclients/searchclientsemaphore.h \
+ control/locationcontroller.h \
+ utils/connectivitymanager.h
+
+FORMS += \
+ ui/theaterwindow.ui \
+ ui/mainwindow.ui \
+ ui/locationdialog.ui \
+ ui/moviewindow.ui \
+ ui/contextdialog.ui \
+ ui/aboutdialog.ui
+
+RESOURCES += \
+ resources.qrc
+
+TRANSLATIONS += \
+ translations/movie-schedule_de.ts
+
+OTHER_FILES += \
+ translations/movie-schedule_de.ts \
+ ../data/movie-schedule.desktop \
+ ../debian/copyright \
+ ../debian/control \
+ ../debian/changelog \
+ ../debian/rules \
+ ../data/clap.xcf \
+ ../README \
+ (Example) \
+ ../COPYING \
+ ../debian/postinst \
+ ../debian/optify \
+ ../debian/compat
+
+!isEmpty(TRANSLATIONS) {
+ isEmpty(QMAKE_LRELEASE) {
+ win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\lrelease.exe
+ else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
+ }
+
+ isEmpty(TS_DIR):TS_DIR = translations
+
+ TSQM.name = lrelease ${QMAKE_FILE_IN}
+ TSQM.input = TRANSLATIONS
+ TSQM.output = $$TS_DIR/${QMAKE_FILE_BASE}.qm
+ TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm $$TS_DIR/${QMAKE_FILE_BASE}.qm
+ TSQM.CONFIG = no_link
+ QMAKE_EXTRA_COMPILERS += TSQM
+
+ PRE_TARGETDEPS += compiler_TSQM_make_all
+}
+
+unix {
+ #VARIABLES
+ isEmpty(PREFIX) {
+ PREFIX = /usr/local
+ DEFINES += DEFAULT_PREFIX
+ }
+
+ BINDIR = $$PREFIX/bin
+ DATADIR =$$PREFIX/share
+
+ DEFINES += DATADIR=\"$$DATADIR\" PKGDATADIR=\"$$PKGDATADIR\"
+
+ #MAKE INSTALL
+
+ INSTALLS += target desktop scalable i18n
+
+ target.path = $$BINDIR
+
+ desktop.path = $$DATADIR/applications/hildon
+ desktop.files += ../data/$${TARGET}.desktop
+
+ scalable.path = $$DATADIR/icons/hicolor/scalable/hildon
+ scalable.files += ../data/scalable/$${TARGET}.png
+
+ i18n.path = $$DATADIR/$${TARGET}
+ i18n.files += ../builddir/src/translations
+
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="de_DE">
+<context>
+ <name>AboutDialog</name>
+ <message>
+ <location filename="../ui/aboutdialog.ui" line="14"/>
+ <source>About</source>
+ <translation>Ãœber</translation>
+ </message>
+ <message>
+ <location filename="../ui/aboutdialog.ui" line="28"/>
+ <source>MovieSchedule</source>
+ <translation>MovieSchedule</translation>
+ </message>
+ <message utf8="true">
+ <location filename="../ui/aboutdialog.ui" line="109"/>
+ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">This software is ©2010 Jochen Becher.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">Movies, Theaters, Schedules and GPS Locations use </span><a href="http://www.google.com"><span style=" font-size:18pt; font-weight:600; text-decoration: underline; color:#2eacff;">Google</span></a><span style=" font-size:18pt;"> services.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">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.</span></p></body></html></source>
+ <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">Diese Software ist ©2010 Jochen Becher.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">Filme, Kinos, Startzeiten und GPS Orte benutzen </span><a href="http://www.google.com"><span style=" font-size:18pt; font-weight:600; text-decoration: underline; color:#2eacff;">Google</span></a><span style=" font-size:18pt;"> Dienste.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version.</span></p></body></html></translation>
+ </message>
+ <message utf8="true">
+ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">This software is ©2010 Jochen Becher.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Movies, Theaters, Schedules and GPS Locations use </span><a href="http://www.google.com"><span style=" font-size:16pt; text-decoration: underline; color:#0000ff;">Google </span></a><span style=" font-size:16pt;">services.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">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.</span></p></body></html></source>
+ <translation type="obsolete"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Diese Software ist ©2010 Jochen Becher.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Filme, Kinos, Startzeiten and GPS Orte benutzen </span><a href="http://www.google.com"><span style=" font-size:16pt; text-decoration: underline; color:#0000ff;">Google </span></a><span style=" font-size:16pt;">Dienste.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach Ihrer Option) jeder späteren Version.</span></p></body></html></translation>
+ </message>
+ <message>
+ <location filename="../ui/aboutdialog.ui" line="143"/>
+ <source>Contact</source>
+ <translation>Kontakt</translation>
+ </message>
+ <message>
+ <location filename="../ui/aboutdialog.ui" line="153"/>
+ <source>Done</source>
+ <translation>Fertig</translation>
+ </message>
+</context>
+<context>
+ <name>ActionController</name>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="79"/>
+ <location filename="../control/actioncontroller.cpp" line="88"/>
+ <location filename="../control/actioncontroller.cpp" line="92"/>
+ <source>Adding calendar event failed.</source>
+ <translation>Hinzufügen des Kalendereintrags fehlgeschlagen.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="83"/>
+ <source>%1 (%2 %3) added to your calendar.</source>
+ <translation>%1 (%2, %3) zum Kalender hinzugefügt.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="109"/>
+ <source>Unable to call theater by phone: communication bus not available.</source>
+ <translation>Telefonanruf fehlgeschlagen: Keine Kommunikation mit dem Telefon möglich.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="114"/>
+ <source>Unable to call theater by phone: phone service not available.</source>
+ <translation>Telefonanruf fehlgeschlagen: Telefonfunktion steht nicht zur Verfügung.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="121"/>
+ <source>Unable to call theater by phone: call failed.</source>
+ <translation>Telefonanruf fehlgeschlagen: Kein Anruf möglich.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="221"/>
+ <source>Unable to search in web: communication bus not available.</source>
+ <translation>Websuche fehlgeschlagen: Kommunikation mit Browser nicht möglich.</translation>
+ </message>
+ <message>
+ <location filename="../control/actioncontroller.cpp" line="226"/>
+ <location filename="../control/actioncontroller.cpp" line="232"/>
+ <source>Unable to search in web: browser service not available.</source>
+ <translation>Websuche fehlgeschlagen: Browser steht nicht zur Verfügung.</translation>
+ </message>
+</context>
+<context>
+ <name>ContextDialog</name>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="14"/>
+ <source>Actions</source>
+ <translation>Aktionen</translation>
+ </message>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="35"/>
+ <source>Add to Calendar</source>
+ <translation>Im Kalender eintragen</translation>
+ </message>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="42"/>
+ <source>Call Theater By Phone</source>
+ <translation>Kino anrufen</translation>
+ </message>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="49"/>
+ <source>Find Route to Theater</source>
+ <translation>Weg zum Kino suchen</translation>
+ </message>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="56"/>
+ <source>Search Movie in Web</source>
+ <translation>Film im Web suchen</translation>
+ </message>
+ <message>
+ <location filename="../ui/contextdialog.ui" line="63"/>
+ <source>Search Theater in Web</source>
+ <translation>Kino im Web suchen</translation>
+ </message>
+</context>
+<context>
+ <name>LocationController</name>
+ <message>
+ <location filename="../control/locationcontroller.cpp" line="25"/>
+ <source>Unable to detect current city.</source>
+ <translation>Die nächste Stadt wurde nicht gefunden.</translation>
+ </message>
+</context>
+<context>
+ <name>LocationDialog</name>
+ <message>
+ <location filename="../ui/locationdialog.ui" line="20"/>
+ <source>Location</source>
+ <translation>Ort</translation>
+ </message>
+ <message>
+ <location filename="../ui/locationdialog.ui" line="49"/>
+ <source>Search Near</source>
+ <translation>In der Nähe suchen</translation>
+ </message>
+ <message>
+ <location filename="../ui/locationdialog.ui" line="116"/>
+ <source>City</source>
+ <translation>Stadt</translation>
+ </message>
+ <message>
+ <location filename="../ui/locationdialog.ui" line="149"/>
+ <source>Search</source>
+ <translation>Suchen</translation>
+ </message>
+</context>
+<context>
+ <name>MainController</name>
+ <message>
+ <source>Unable to access network</source>
+ <translation type="obsolete">Netzwerk steht nicht zur Verfügung.</translation>
+ </message>
+ <message>
+ <location filename="../control/maincontroller.cpp" line="43"/>
+ <source>Unable to access network.</source>
+ <translation>Netzwerk steht nicht zur Verfügung.</translation>
+ </message>
+ <message>
+ <location filename="../control/maincontroller.cpp" line="44"/>
+ <source>No theaters found near %1.</source>
+ <translation>Keine Kinos in der Nähe von %1 gefunden.</translation>
+ </message>
+ <message>
+ <location filename="../control/maincontroller.cpp" line="45"/>
+ <source>No movies found near %1.</source>
+ <translation>Keine Filme in der Nähe von %1 gefunden.</translation>
+ </message>
+ <message>
+ <location filename="../control/maincontroller.cpp" line="46"/>
+ <source>Error on fetching theaters.</source>
+ <translation>Fehler beim Lesen der Kinoliste.</translation>
+ </message>
+ <message>
+ <location filename="../control/maincontroller.cpp" line="47"/>
+ <source>Error on fetching movies.</source>
+ <translation>Fehler beim Lesen der Filmliste.</translation>
+ </message>
+</context>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="75"/>
+ <location filename="../ui/mainwindow.cpp" line="113"/>
+ <source>Movies</source>
+ <translation>Filme</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="76"/>
+ <location filename="../ui/mainwindow.cpp" line="105"/>
+ <source>Theaters</source>
+ <translation>Kinos</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="77"/>
+ <source>Location</source>
+ <translation>Ort</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="78"/>
+ <source>About</source>
+ <translation>Ãœber</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="80"/>
+ <source>Call By Phone</source>
+ <translation>Kino anrufen</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="81"/>
+ <source>Find Route</source>
+ <translation>Weg zum Kino suchen</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.cpp" line="82"/>
+ <location filename="../ui/mainwindow.cpp" line="84"/>
+ <source>Search In Web</source>
+ <translation>Im Web suchen</translation>
+ </message>
+ <message>
+ <source>Movie-Schedule</source>
+ <translation type="obsolete">Kinoprogramm</translation>
+ </message>
+ <message>
+ <location filename="../ui/mainwindow.ui" line="14"/>
+ <location filename="../ui/mainwindow.cpp" line="120"/>
+ <source>MovieSchedule</source>
+ <translation>MovieSchedule</translation>
+ </message>
+</context>
+<context>
+ <name>MovieController</name>
+ <message>
+ <location filename="../control/moviecontroller.cpp" line="35"/>
+ <source>No schedule found for %1.</source>
+ <translation>Kein Kinoprogramm für %1 gefunden.</translation>
+ </message>
+ <message>
+ <location filename="../control/moviecontroller.cpp" line="36"/>
+ <source>Error on fetching movie schedule.</source>
+ <translation>Fehler beim Lesen des Kinoprogramms.</translation>
+ </message>
+</context>
+<context>
+ <name>MovieWindow</name>
+ <message>
+ <location filename="../ui/moviewindow.ui" line="14"/>
+ <source>Movie</source>
+ <translation>Film</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../utils/timeutils.cpp" line="79"/>
+ <source>Today</source>
+ <comment>DayPainter</comment>
+ <translation>Heute</translation>
+ </message>
+ <message>
+ <location filename="../utils/timeutils.cpp" line="81"/>
+ <source>Tomorrow</source>
+ <comment>DayPainter</comment>
+ <translation>Morgen</translation>
+ </message>
+ <message>
+ <location filename="../ui/moviepainter.cpp" line="52"/>
+ <source>%1min</source>
+ <comment>movie duration</comment>
+ <translation>%1Min</translation>
+ </message>
+</context>
+<context>
+ <name>TheaterController</name>
+ <message>
+ <location filename="../control/theatercontroller.cpp" line="35"/>
+ <source>No schedule found for %1.</source>
+ <translation>Kein Kinoprogramm für %1 gefunden.</translation>
+ </message>
+ <message>
+ <location filename="../control/theatercontroller.cpp" line="36"/>
+ <source>Error on fetching theater schedule.</source>
+ <translation>Fehler beim Lesen des Kinoprogramms.</translation>
+ </message>
+</context>
+<context>
+ <name>TheaterWindow</name>
+ <message>
+ <location filename="../ui/theaterwindow.ui" line="14"/>
+ <source>Theater</source>
+ <translation>Kino</translation>
+ </message>
+</context>
+</TS>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "aboutdialog.h"
+#include "ui_aboutdialog.h"
+
+AboutDialog::AboutDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::AboutDialog)
+{
+ ui->setupUi(this);
+ ui->_button_box->addButton(ui->_done_button, QDialogButtonBox::AcceptRole);
+ ui->_button_box->addButton(ui->_contact_button, QDialogButtonBox::ActionRole);
+ //QPalette palette = ui->_about_text->palette();
+ //palette.setColor(QPalette::Base, palette.color(QPalette::Window));
+ //palette.setColor(QPalette::Text, palette.color(QPalette::WindowText));
+ //ui->_about_text->setPalette(palette);
+ connect(ui->_button_box, SIGNAL(accepted()), this, SLOT(deleteLater()));
+ connect(ui->_button_box, SIGNAL(rejected()), this, SLOT(deleteLater()));
+ connect(ui->_contact_button, SIGNAL(clicked()), this, SLOT(deleteLater()));
+ connect(ui->_contact_button, SIGNAL(clicked()), this, SIGNAL(ContactAuthor()));
+}
+
+AboutDialog::~AboutDialog()
+{
+ delete ui;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ABOUTDIALOG_H
+#define ABOUTDIALOG_H
+
+#include <QDialog>
+
+namespace Ui {
+ class AboutDialog;
+}
+
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AboutDialog(QWidget *parent = 0);
+ ~AboutDialog();
+
+public:
+ Q_SIGNAL void ContactAuthor();
+
+private:
+ Ui::AboutDialog *ui;
+};
+
+#endif // ABOUTDIALOG_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialog</class>
+ <widget class="QDialog" name="AboutDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>443</width>
+ <height>233</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>About</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="_title">
+ <property name="font">
+ <font>
+ <family>Sans Serif</family>
+ <pointsize>22</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>MovieSchedule</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" rowspan="4">
+ <widget class="QDialogButtonBox" name="_button_box">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" rowspan="6">
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>311</width>
+ <height>434</height>
+ </rect>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="Base">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="_about_text">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">This software is ©2010 Jochen Becher.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt;">Movies, Theaters, Schedules and GPS Locations use </span><a href="http://www.google.com"><span style=" font-size:18pt; font-weight:600; text-decoration: underline; color:#2eacff;">Google</span></a><span style=" font-size:18pt;"> services.</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">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.</span></p></body></html></string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="_contact_button">
+ <property name="text">
+ <string>Contact</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="_done_button">
+ <property name="text">
+ <string>Done</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "abstractmainwindow.h"
+
+#include <QContextMenuEvent>
+
+AbstractMainWindow::AbstractMainWindow(QWidget *parent)
+ : QMainWindow(parent)
+{
+}
+
+void AbstractMainWindow::SetBusy(bool busy)
+{
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5ShowProgressIndicator, busy);
+#else
+ if (busy) {
+ setCursor(QCursor(Qt::WaitCursor));
+ } else {
+ setCursor(QCursor());
+ }
+#endif
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ABSTRACTMAINWINDOW_H
+#define ABSTRACTMAINWINDOW_H
+
+#include <QMainWindow>
+#include <QPoint>
+
+class AbstractMainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ explicit AbstractMainWindow(QWidget *parent = 0);
+
+public:
+ Q_SLOT void SetBusy(bool busy);
+
+};
+
+#endif // ABSTRACTMAINWINDOW_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "backgroundlabel.h"
+
+#include <QPainter>
+#include <QFont>
+
+static const int MINIMUM_FONT_SIZE = 40;
+
+BackgroundLabel::BackgroundLabel(QWidget *parent)
+ : QWidget(parent),
+ _cached_label_font_size(0),
+ _cached_label_alignment(Qt::AlignHCenter | Qt::AlignTop)
+{
+}
+
+void BackgroundLabel::SetLabelText(const QString &label_text)
+{
+ _label_text = label_text;
+ _cached_label_font_size = 0;
+ update();
+}
+
+void BackgroundLabel::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+
+ QPainter painter(this);
+
+ QFont label_font = font();
+ label_font.setWeight(QFont::Black);
+
+ painter.translate(rect().width(), 0);
+ painter.rotate(90);
+
+ QRect widget_rect = painter.worldTransform().inverted().mapRect(rect());
+ if (_cached_label_font_size <= 0 || widget_rect != _cached_widget_rect) {
+ _cached_widget_rect = widget_rect;
+ _cached_label_rect = widget_rect;
+ _cached_label_rect.setTop(_cached_label_rect.top() + 20);
+ _cached_label_alignment = Qt::AlignHCenter | Qt::AlignTop;
+ int font_size = 80;
+
+ for (;;) {
+ label_font.setPixelSize(font_size);
+ painter.setFont(label_font);
+ QRect label_rect = painter.boundingRect(_cached_label_rect, _cached_label_alignment, _label_text);
+ if (label_rect.x() < _cached_widget_rect.x()
+ || label_rect.y() < _cached_widget_rect.y()
+ || label_rect.width() > _cached_widget_rect.width()
+ || label_rect.height() > _cached_widget_rect.height()) {
+ font_size = font_size * 0.9;
+ if (font_size < MINIMUM_FONT_SIZE) {
+ font_size = MINIMUM_FONT_SIZE;
+ _cached_label_alignment = Qt::AlignLeft | Qt::AlignTop;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ _cached_label_font_size = font_size;
+ } else {
+ label_font.setPixelSize(_cached_label_font_size);
+ painter.setFont(label_font);
+ }
+ QColor text_color = palette().color(QPalette::WindowText);
+ text_color.setAlpha(32);
+ painter.setPen(text_color);
+ painter.drawText(_cached_label_rect, _cached_label_alignment, _label_text);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef BACKGROUNDLABEL_H
+#define BACKGROUNDLABEL_H
+
+#include <QWidget>
+
+class BackgroundLabel : public QWidget
+{
+ Q_OBJECT
+public:
+ BackgroundLabel(QWidget *parent);
+
+public slots:
+ void SetLabelText(const QString &label_text);
+
+protected:
+ void paintEvent(QPaintEvent *event);
+
+private:
+ QString _label_text;
+ QRect _cached_widget_rect;
+ QRect _cached_label_rect;
+ int _cached_label_font_size;
+ Qt::Alignment _cached_label_alignment;
+};
+
+#endif // BACKGROUNDLABEL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "cinemapainter.h"
+
+#include "data/cinema.h"
+#include "ui/styleutils.h"
+
+#include <QPainter>
+#include <QStyleOptionViewItem>
+
+CinemaPainter::CinemaPainter()
+{
+}
+
+void CinemaPainter::Paint(QPainter *painter, const QStyleOptionViewItem &option, const Cinema *cinema) const
+{
+ painter->setFont(option.font);
+ painter->setPen(StyleUtils::INSTANCE()->GetColor(option.palette, StyleUtils::DefaultTextColor));
+ painter->drawText(0, painter->fontMetrics().ascent(), cinema->GetName());
+ int y = painter->fontMetrics().height() + 2;
+ QRect bounding_rect;
+ painter->setPen(StyleUtils::INSTANCE()->GetColor(option.palette, StyleUtils::SecondaryTextColor));
+ bool drawn = false;
+ if (!cinema->GetAddress().isEmpty()) {
+ QFont font2(option.font);
+ font2.setPointSizeF(font2.pointSizeF() * 0.7);
+ painter->setFont(font2);
+ painter->drawText(0, y, 1000, painter->fontMetrics().height(),
+ 0, cinema->GetAddress(), &bounding_rect);
+ drawn = true;
+ }
+ if (!cinema->GetTelephone().isEmpty()) {
+ painter->drawText(bounding_rect.right(), y, 1000, painter->fontMetrics().height(),
+ 0, QString((drawn ? ", %1" : "%1")).arg(cinema->GetTelephone()), &bounding_rect);
+ }
+}
+
+QSize CinemaPainter::GetSizeHint(const QStyleOptionViewItem &option) const
+{
+ return QSize(0, option.fontMetrics.height() + 2 + option.fontMetrics.height() * 0.7 + 4);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CINEMAPAINTER_H
+#define CINEMAPAINTER_H
+
+#include <QSize>
+
+class QPainter;
+class QStyleOptionViewItem;
+class Cinema;
+
+class CinemaPainter
+{
+public:
+ CinemaPainter();
+
+ void Paint(QPainter *painter, const QStyleOptionViewItem &option, const Cinema *cinema) const;
+
+ QSize GetSizeHint(const QStyleOptionViewItem &option) const;
+
+};
+
+#endif // CINEMAPAINTER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "contextdialog.h"
+#include "ui_contextdialog.h"
+
+#include "data/cinemaschedule.h"
+#include "data/scheduleentrykey.h"
+#include "data/cinema.h"
+#include "data/movie.h"
+#include "utils/assertedlocker.h"
+
+#include <QLayoutItem>
+
+ContextDialog::ContextDialog(CinemaSchedule *cinema_schedule, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::ContextDialog),
+ _cinema_schedule(cinema_schedule),
+ _next_row(0),
+ _next_column(0)
+{
+ ui->setupUi(this);
+ removeAllWidgets();
+ connect(ui->add_to_calendar, SIGNAL(clicked()), this, SLOT(AddToCalendar()));
+ connect(ui->call_theater_by_phone, SIGNAL(clicked()), this, SLOT(CallTheaterByPhone()));
+ connect(ui->find_route_to_theater, SIGNAL(clicked()), this, SLOT(FindRouteToTheater()));
+ connect(ui->search_movie_in_web, SIGNAL(clicked()), this, SLOT(SearchMovieInWeb()));
+ connect(ui->search_theater_in_web, SIGNAL(clicked()), this, SLOT(SearchTheaterInWeb()));
+}
+
+ContextDialog::~ContextDialog()
+{
+ delete ui;
+}
+
+void ContextDialog::Show(ScheduleEntryKey schedule_entry_key)
+{
+ removeAllWidgets();
+ _schedule_entry_key = schedule_entry_key;
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ ScheduleEntry schedule_entry = _cinema_schedule->FindScheduleEntry(_schedule_entry_key);
+ if (schedule_entry.IsValid()) {
+ addWidget(ui->add_to_calendar);
+ if (!schedule_entry.GetCinema()->GetTelephone().isEmpty()) {
+ addWidget(ui->call_theater_by_phone);
+ }
+ if (!schedule_entry.GetCinema()->GetAddress().isEmpty()) {
+ // TODO enable if find route is implemented
+ // addWidget(ui->find_route_to_theater);
+ }
+ addWidget(ui->search_movie_in_web);
+ if (!schedule_entry.GetCinema()->GetAddress().isEmpty()) {
+ addWidget(ui->search_theater_in_web);
+ }
+ adjustSize();
+ show();
+ }
+}
+
+void ContextDialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void ContextDialog::removeAllWidgets()
+{
+ QLayoutItem *item;
+ while ((item = ui->gridLayout->itemAt(0)) != 0) {
+ if (item->widget() != 0) {
+ item->widget()->setVisible(false);
+ }
+ ui->gridLayout->removeItem(item);
+ }
+ _next_row = 0;
+ _next_column = 0;
+}
+
+void ContextDialog::addWidget(QWidget *widget)
+{
+ widget->setVisible(true);
+ ui->gridLayout->addWidget(widget, _next_row, _next_column, 1, 1);
+ ++_next_column;
+ if (_next_column > 1) {
+ ++_next_row;
+ _next_column = 0;
+ }
+}
+
+void ContextDialog::AddToCalendar()
+{
+ hide();
+ emit AddToCalendar(_schedule_entry_key);
+}
+
+void ContextDialog::CallTheaterByPhone()
+{
+ hide();
+ emit CallTheaterByPhone(_schedule_entry_key.GetCinemaKey());
+}
+
+void ContextDialog::FindRouteToTheater()
+{
+ hide();
+ emit FindRouteToTheater(_schedule_entry_key.GetCinemaKey());
+}
+
+void ContextDialog::SearchMovieInWeb()
+{
+ hide();
+ emit SearchMovieInWeb(_schedule_entry_key.GetMovieKey());
+}
+
+void ContextDialog::SearchTheaterInWeb()
+{
+ hide();
+ emit SearchTheaterInWeb(_schedule_entry_key.GetCinemaKey());
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CONTEXTDIALOG_H
+#define CONTEXTDIALOG_H
+
+#include "data/cinemakey.h"
+#include "data/moviekey.h"
+#include "data/scheduleentrykey.h"
+
+#include <QDialog>
+
+class CinemaSchedule;
+
+namespace Ui {
+ class ContextDialog;
+}
+
+class ContextDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ContextDialog(CinemaSchedule *cinema_schedule, QWidget *parent = 0);
+ ~ContextDialog();
+
+public:
+ Q_SIGNAL void AddToCalendar(ScheduleEntryKey);
+ Q_SIGNAL void CallTheaterByPhone(CinemaKey);
+ Q_SIGNAL void FindRouteToTheater(CinemaKey);
+ Q_SIGNAL void SearchMovieInWeb(MovieKey);
+ Q_SIGNAL void SearchTheaterInWeb(CinemaKey);
+
+public:
+ Q_SLOT void Show(ScheduleEntryKey schedule_entry_key);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ void removeAllWidgets();
+ void addWidget(QWidget *);
+
+ Q_SLOT void AddToCalendar();
+ Q_SLOT void CallTheaterByPhone();
+ Q_SLOT void FindRouteToTheater();
+ Q_SLOT void SearchMovieInWeb();
+ Q_SLOT void SearchTheaterInWeb();
+
+private:
+ Ui::ContextDialog *ui;
+ CinemaSchedule *_cinema_schedule;
+ ScheduleEntryKey _schedule_entry_key;
+ int _next_row;
+ int _next_column;
+};
+
+#endif // CONTEXTDIALOG_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ContextDialog</class>
+ <widget class="QDialog" name="ContextDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>339</width>
+ <height>105</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Actions</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0">
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="add_to_calendar">
+ <property name="text">
+ <string>Add to Calendar</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QPushButton" name="call_theater_by_phone">
+ <property name="text">
+ <string>Call Theater By Phone</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="find_route_to_theater">
+ <property name="text">
+ <string>Find Route to Theater</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QPushButton" name="search_movie_in_web">
+ <property name="text">
+ <string>Search Movie in Web</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QPushButton" name="search_theater_in_web">
+ <property name="text">
+ <string>Search Theater in Web</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "daypainter.h"
+#include "utils/timeutils.h"
+#include "ui/styleutils.h"
+
+#include <QPainter>
+#include <QStyleOptionViewItem>
+#include <QDate>
+
+DayPainter::DayPainter()
+{
+}
+
+void DayPainter::Paint(QPainter *painter, const QStyleOptionViewItem &option, const QDate &date) const
+{
+ QString date_name = TimeUtils::ToDateString(date);
+ QFont bigfont(option.font);
+ bigfont.setPointSizeF(bigfont.pointSizeF() * 1.5);
+ painter->setFont(bigfont);
+ QRectF text_rect = painter->boundingRect(option.rect, Qt::AlignCenter, date_name);
+ text_rect.setWidth(text_rect.width() + 16);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(StyleUtils::INSTANCE()->GetDayBackgroundColor(option.palette, date));
+ painter->drawRoundedRect(32, 2, text_rect.width(), text_rect.height(), 5, 5);
+ painter->setPen(StyleUtils::INSTANCE()->GetDayTextColor(option.palette, date));
+ painter->drawText(32, 2, text_rect.width(), text_rect.height(), Qt::AlignCenter, date_name);
+}
+
+QSize DayPainter::GetSizeHint(const QStyleOptionViewItem &option) const
+{
+ return QSize(0, option.fontMetrics.height() * 1.5 + 4);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DAYPAINTER_H
+#define DAYPAINTER_H
+
+#include <QSize>
+
+class QPainter;
+class QStyleOptionViewItem;
+class QDate;
+
+class DayPainter
+{
+public:
+ DayPainter();
+
+ void Paint(QPainter *painter, const QStyleOptionViewItem &option, const QDate &date) const;
+
+ QSize GetSizeHint(const QStyleOptionViewItem &option) const;
+
+};
+
+#endif // DAYPAINTER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "locationdialog.h"
+#include "ui_locationdialog.h"
+
+LocationDialog::LocationDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::LocationDialog)
+{
+ ui->setupUi(this);
+ ui->_button_box->addButton(ui->Search, QDialogButtonBox::AcceptRole);
+ connect(ui->_button_box, SIGNAL(accepted()), this, SLOT(SearchClicked()));
+ connect(ui->_button_box, SIGNAL(rejected()), this, SLOT(deleteLater()));
+ connect(ui->GPS, SIGNAL(clicked()), this, SLOT(GPSClicked()));
+ connect(ui->Location1, SIGNAL(clicked()), this, SLOT(PreviousLocation1Clicked()));
+ connect(ui->Location2, SIGNAL(clicked()), this, SLOT(PreviousLocation2Clicked()));
+ connect(ui->Location3, SIGNAL(clicked()), this, SLOT(PreviousLocation3Clicked()));
+ connect(ui->Location4, SIGNAL(clicked()), this, SLOT(PreviousLocation4Clicked()));
+ connect(ui->Location5, SIGNAL(clicked()), this, SLOT(PreviousLocation5Clicked()));
+ connect(this, SIGNAL(accepted()), this, SLOT(SearchClicked()));
+ connect(this, SIGNAL(rejected()), this, SIGNAL(Cancel()));
+ _location_buttons.append(ui->Location1);
+ _location_buttons.append(ui->Location2);
+ _location_buttons.append(ui->Location3);
+ _location_buttons.append(ui->Location4);
+ _location_buttons.append(ui->Location5);
+}
+
+LocationDialog::~LocationDialog()
+{
+ delete ui;
+}
+
+void LocationDialog::SetLocation(const Location &location)
+{
+ ui->Location->setText(location.GetLocationName());
+}
+
+void LocationDialog::SetPreviousLocations(const Locations &previous_locations)
+{
+ _previous_locations = previous_locations;
+ QListIterator<Location> it(_previous_locations);
+ int i = 0;
+ while (it.hasNext() && i < _location_buttons.size()) {
+ const Location &location = it.next();
+ if (location.IsValid()) {
+ _location_buttons[i]->setText(location.GetLocationName());
+ _location_buttons[i]->setVisible(true);
+ _location_buttons[i]->setEnabled(true);
+ ++i;
+ }
+ }
+ while (i < _location_buttons.size()) {
+ _location_buttons[i]->setVisible(false);
+ _location_buttons[i]->setEnabled(false);
+ ++i;
+ }
+}
+
+void LocationDialog::SetGPSEnabled(bool gps_enabled)
+{
+ ui->GPS->setVisible(gps_enabled);
+ ui->GPS->setEnabled(gps_enabled);
+}
+
+void LocationDialog::show()
+{
+ ui->gridLayout->removeWidget(ui->GPS);
+ for (int i = 0; i < _location_buttons.size(); ++i) {
+ ui->gridLayout->removeWidget(_location_buttons[i]);
+ }
+ int row = 0;
+ int column = 0;
+ if (ui->GPS->isEnabled()) {
+ ui->gridLayout->addWidget(ui->GPS, row, column);
+ ++column;
+ }
+ for (int i = 0; i < _location_buttons.size(); ++i) {
+ if (_location_buttons[i]->isEnabled()) {
+ ui->gridLayout->addWidget(_location_buttons[i], row, column);
+ ++column;
+ if (column > 1) {
+ ++row;
+ column = 0;
+ }
+ }
+ }
+ for (int i = 0; i < _location_buttons.size(); ++i) {
+ if (_location_buttons[i]->text() == ui->Location->text()) {
+ ui->Location->setText("");
+ break;
+ }
+ }
+ adjustSize();
+ ui->Search->setDefault(true);
+ ui->Location->setFocus();
+ QDialog::show();
+}
+
+void LocationDialog::SearchClicked()
+{
+ Location location;
+ location.SetLocationName(ui->Location->text());
+ if (location.IsValid()) {
+ emit Search(location);
+ hide();
+ deleteLater();
+ }
+}
+
+void LocationDialog::GPSClicked()
+{
+ emit SearchGPS();
+ hide();
+ deleteLater();
+}
+
+void LocationDialog::PreviousLocation1Clicked()
+{
+ PreviousLocationClicked(0);
+}
+
+void LocationDialog::PreviousLocation2Clicked()
+{
+ PreviousLocationClicked(1);
+}
+
+void LocationDialog::PreviousLocation3Clicked()
+{
+ PreviousLocationClicked(2);
+}
+
+void LocationDialog::PreviousLocation4Clicked()
+{
+ PreviousLocationClicked(3);
+}
+
+void LocationDialog::PreviousLocation5Clicked()
+{
+ PreviousLocationClicked(4);
+}
+
+void LocationDialog::PreviousLocationClicked(int i)
+{
+ Location location;
+ location.SetLocationName(_location_buttons[i]->text());
+ emit SearchPreviousLocation(location);
+ hide();
+ deleteLater();
+}
+
+void LocationDialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef LOCATIONDIALOG_H
+#define LOCATIONDIALOG_H
+
+#include "data/location.h"
+
+#include <QDialog>
+#include <QList>
+#include <QVector>
+
+class QPushButton;
+
+namespace Ui {
+ class LocationDialog;
+}
+
+class LocationDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ typedef QList<Location> Locations;
+
+public:
+ explicit LocationDialog(QWidget *parent = 0);
+ ~LocationDialog();
+
+ void SetLocation(const Location &location);
+
+ void SetPreviousLocations(const Locations &);
+
+ void SetGPSEnabled(bool gps_enabled);
+
+ void show();
+
+public:
+ Q_SIGNAL void Search(Location location);
+ Q_SIGNAL void SearchPreviousLocation(Location location);
+ Q_SIGNAL void SearchGPS();
+ Q_SIGNAL void Cancel();
+
+private:
+ Q_SLOT void SearchClicked();
+ Q_SLOT void GPSClicked();
+ Q_SLOT void PreviousLocation1Clicked();
+ Q_SLOT void PreviousLocation2Clicked();
+ Q_SLOT void PreviousLocation3Clicked();
+ Q_SLOT void PreviousLocation4Clicked();
+ Q_SLOT void PreviousLocation5Clicked();
+
+private:
+ void PreviousLocationClicked(int i);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Ui::LocationDialog *ui;
+ Locations _previous_locations;
+ QVector<QPushButton *> _location_buttons;
+};
+
+#endif // LOCATIONDIALOG_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LocationDialog</class>
+ <widget class="QDialog" name="LocationDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>280</width>
+ <height>140</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Location</string>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="GPS">
+ <property name="text">
+ <string>Search Near</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QPushButton" name="Location1">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="Location2">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="Location3">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="Location4">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="Location5">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="CityLabel">
+ <property name="text">
+ <string>City</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="Location">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="_button_box">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="Search">
+ <property name="text">
+ <string>Search</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include "theatermodel.h"
+#include "theaterdelegate.h"
+#include "moviemodel.h"
+#include "moviedelegate.h"
+#include "locationdialog.h"
+#include "data/cinemaschedule.h"
+#include "data/cinema.h"
+#include "data/movie.h"
+#include "data/cinemakey.h"
+#include "data/moviekey.h"
+#include "data/cinemakey.h"
+#include "utils/assertedlocker.h"
+
+#include <QCursor>
+#include <QtGui>
+#ifdef Q_WS_MAEMO_5
+#include <QAbstractKineticScroller>
+#endif
+#include <iostream>
+
+MainWindow::MainWindow(const CinemaSchedule *cinema_schedule, QWidget *parent) :
+ AbstractMainWindow(parent),
+ ui(new Ui::MainWindow),
+ _cinema_schedule(cinema_schedule),
+ _theater_context_menu(0),
+ _movie_context_menu(0),
+ _theater_phone_call(0),
+ _theater_find_route(0),
+ _theater_search_web(0),
+ _movie_search_web(0),
+ _theater_model(0),
+ _movie_model(0)
+{
+ ui->setupUi(this);
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+ QStackedLayout *layout = dynamic_cast<QStackedLayout*>(ui->MainStack->layout());
+ if (layout != 0) {
+ layout->setStackingMode(QStackedLayout::StackAll);
+ }
+ ui->Theaters->setItemDelegate(new TheaterDelegate(this));
+ ui->Theaters->setProperty("FingerScrollable", true);
+ ui->Theaters->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->Movies->setItemDelegate(new MovieDelegate(this));
+ ui->Movies->setProperty("FingerScrollable", true);
+ ui->Movies->setContextMenuPolicy(Qt::CustomContextMenu);
+ QFont f(font());
+ f.setPointSizeF(f.pointSizeF() * 1.5);
+ ui->ErrorMessage->setFont(f);
+ connect(ui->Theaters, SIGNAL(clicked(QModelIndex)), this, SLOT(TheaterClicked(QModelIndex)));
+ connect(ui->Theaters, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(TheaterContextMenuRequested(QPoint)));
+ connect(ui->Movies, SIGNAL(clicked(QModelIndex)), this, SLOT(MovieClicked(QModelIndex)));
+ connect(ui->Movies, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(MovieContextMenuRequested(QPoint)));
+ ui->menubar->addAction(tr("Movies"), this, SIGNAL(SearchMovies()));
+ ui->menubar->addAction(tr("Theaters"), this, SIGNAL(SearchTheaters()));
+ ui->menubar->addAction(tr("Location"), this, SIGNAL(OpenLocationDialog()));
+ ui->menubar->addAction(tr("About"), this, SIGNAL(OpenAboutDialog()));
+ _theater_context_menu = new QMenu(this);
+ _theater_phone_call = _theater_context_menu->addAction(tr("Call By Phone"), this, SLOT(CallTheaterByPhone()));
+ _theater_find_route = _theater_context_menu->addAction(tr("Find Route"), this, SLOT(FindRouteToTheater()));
+ _theater_search_web = _theater_context_menu->addAction(tr("Search In Web"), this, SLOT(SearchTheaterInWeb()));
+ _movie_context_menu = new QMenu(this);
+ _movie_search_web = _movie_context_menu->addAction(tr("Search In Web"), this, SLOT(SearchMovieInWeb()));
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::SetLocation(Location location)
+{
+ _location = location;
+ if (_location.IsValid()) {
+ ui->Background->SetLabelText(_location.GetLocationName());
+ } else {
+ ui->Background->SetLabelText("");
+ }
+}
+
+void MainWindow::SetTheaterModel(QAbstractItemModel *theater_model)
+{
+ _theater_model = theater_model;
+ setWindowTitle(tr("Theaters"));
+ ui->Theaters->setModel(theater_model);
+ ui->MainPages->setCurrentWidget(ui->TheatersPage);
+}
+
+void MainWindow::SetMovieModel(QAbstractItemModel *movie_model)
+{
+ _movie_model = movie_model;
+ setWindowTitle(tr("Movies"));
+ ui->Movies->setModel(movie_model);
+ ui->MainPages->setCurrentWidget(ui->MoviesPage);
+}
+
+void MainWindow::SetError(QString error_text)
+{
+ setWindowTitle(tr("MovieSchedule"));
+ ui->ErrorMessage->setText(error_text);
+ ui->MainPages->setCurrentWidget(ui->ErrorPage);
+}
+
+void MainWindow::TheaterClicked(QModelIndex index)
+{
+ emit TheaterSelected(GetCinema(index));
+}
+
+void MainWindow::TheaterContextMenuRequested(const QPoint &pos)
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Cinema *cinema = _cinema_schedule->FindCinema(GetCinema(ui->Theaters->currentIndex()));
+ if (cinema != 0) {
+ ShowContextMenu(cinema, ui->Theaters->viewport()->mapToGlobal(pos));
+ }
+}
+
+void MainWindow::MovieClicked(QModelIndex index)
+{
+ emit MovieSelected(GetMovie(index));
+}
+
+void MainWindow::MovieContextMenuRequested(const QPoint &pos)
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Movie *movie = _cinema_schedule->FindMovie(GetMovie(ui->Movies->currentIndex()));
+ if (movie != 0) {
+ ShowContextMenu(movie, ui->Movies->viewport()->mapToGlobal(pos));
+ }
+}
+
+void MainWindow::CallTheaterByPhone()
+{
+ emit CallTheaterByPhone(GetCinema(ui->Theaters->currentIndex()));
+}
+
+void MainWindow::FindRouteToTheater()
+{
+ emit FindRouteToTheater(GetCinema(ui->Theaters->currentIndex()));
+}
+
+void MainWindow::SearchTheaterInWeb()
+{
+ emit SearchTheaterInWeb(GetCinema(ui->Theaters->currentIndex()));
+}
+
+void MainWindow::SearchMovieInWeb()
+{
+ emit SearchMovieInWeb(GetMovie(ui->Movies->currentIndex()));
+}
+
+void MainWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+CinemaKey MainWindow::GetCinema(const QModelIndex &index)
+{
+ QVariant var = _theater_model->data(index, TheaterModel::TheaterKeyRole);
+ CinemaKey cinema_key = qVariantValue<CinemaKey>(var);
+ return cinema_key;
+}
+
+MovieKey MainWindow::GetMovie(const QModelIndex &index)
+{
+ QVariant var = _movie_model->data(index, MovieModel::MovieKeyRole);
+ MovieKey movie_key = qVariantValue<MovieKey>(var);
+ return movie_key;
+}
+
+void MainWindow::ShowContextMenu(const Cinema *cinema, const QPoint &pos)
+{
+ _theater_phone_call->setVisible(!cinema->GetTelephone().isEmpty());
+ // TODO enable if find-route works
+ _theater_find_route->setVisible(false && !cinema->GetAddress().isEmpty());
+ _theater_search_web->setVisible(true);
+ _theater_context_menu->popup(pos);
+}
+
+void MainWindow::ShowContextMenu(const Movie *movie, const QPoint &pos)
+{
+ Q_UNUSED(movie);
+ _movie_search_web->setVisible(true);
+ _movie_context_menu->popup(pos);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "abstractmainwindow.h"
+#include "data/location.h"
+#include "data/cinemakey.h"
+#include "data/moviekey.h"
+
+#include <QModelIndex>
+
+class CinemaSchedule;
+class Cinema;
+class Movie;
+class QAbstractItemModel;
+class QMenu;
+class QAction;
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public AbstractMainWindow {
+ Q_OBJECT
+public:
+ explicit MainWindow(const CinemaSchedule *cinema_schedule, QWidget *parent = 0);
+ ~MainWindow();
+
+public:
+ Q_SLOT void SetLocation(Location location);
+ Q_SLOT void SetTheaterModel(QAbstractItemModel *);
+ Q_SLOT void SetMovieModel(QAbstractItemModel *);
+ Q_SLOT void SetError(QString error_text);
+
+public:
+ Q_SIGNAL void SearchTheaters();
+ Q_SIGNAL void SearchMovies();
+ Q_SIGNAL void OpenLocationDialog();
+ Q_SIGNAL void OpenAboutDialog();
+ Q_SIGNAL void TheaterSelected(CinemaKey);
+ Q_SIGNAL void MovieSelected(MovieKey);
+ Q_SIGNAL void CallTheaterByPhone(CinemaKey);
+ Q_SIGNAL void FindRouteToTheater(CinemaKey);
+ Q_SIGNAL void SearchTheaterInWeb(CinemaKey);
+ Q_SIGNAL void SearchMovieInWeb(MovieKey);
+
+private:
+ Q_SLOT void TheaterClicked(QModelIndex);
+ Q_SLOT void TheaterContextMenuRequested(const QPoint &);
+ Q_SLOT void MovieClicked(QModelIndex);
+ Q_SLOT void MovieContextMenuRequested(const QPoint &);
+ Q_SLOT void CallTheaterByPhone();
+ Q_SLOT void FindRouteToTheater();
+ Q_SLOT void SearchTheaterInWeb();
+ Q_SLOT void SearchMovieInWeb();
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ CinemaKey GetCinema(const QModelIndex &index);
+ MovieKey GetMovie(const QModelIndex &index);
+ void ShowContextMenu(const Cinema *, const QPoint &pos);
+ void ShowContextMenu(const Movie *, const QPoint &pos);
+
+private:
+ Ui::MainWindow *ui;
+ const CinemaSchedule *_cinema_schedule;
+ QMenu *_theater_context_menu;
+ QMenu *_movie_context_menu;
+ QAction *_theater_phone_call;
+ QAction *_theater_find_route;
+ QAction *_theater_search_web;
+ QAction *_movie_search_web;
+ Location _location;
+ QAbstractItemModel *_theater_model;
+ QAbstractItemModel *_movie_model;
+};
+
+#endif // MAINWINDOW_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MovieSchedule</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="MainStack">
+ <widget class="QWidget" name="contentsPage">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="MainPages">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QListView {
+ background: rgba(255, 255, 255, 0)
+}
+QLabel {
+ background: rgba(255, 255, 255, 0)
+}</string>
+ </property>
+ <property name="currentIndex">
+ <number>2</number>
+ </property>
+ <widget class="QWidget" name="TheatersPage">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="Theaters">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="MoviesPage">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="Movies">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="ErrorPage">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="ErrorMessage">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="backgroundPage">
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="BackgroundLabel" name="Background" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>BackgroundLabel</class>
+ <extends>QWidget</extends>
+ <header>ui/backgroundlabel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviedelegate.h"
+
+#include "moviemodel.h"
+
+#include <QPainter>
+
+MovieDelegate::MovieDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void MovieDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<MovieItem>(index.data())) {
+ MovieItem item = qVariantValue<MovieItem>(index.data());
+ painter->save();
+ painter->translate(option.rect.x(), option.rect.y());
+ _movie_painter.Paint(painter, option, item.GetMovie());
+ painter->restore();
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize MovieDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ if (qVariantCanConvert<MovieItem>(index.data())) {
+ return _movie_painter.GetSizeHint(option);
+ } else {
+ return QStyledItemDelegate::sizeHint(option, index);
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIEDELEGATE_H
+#define MOVIEDELEGATE_H
+
+#include "moviepainter.h"
+
+#include <QStyledItemDelegate>
+
+class MovieDelegate : public QStyledItemDelegate
+{
+public:
+ MovieDelegate(QWidget *parent = 0);
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private:
+ MoviePainter _movie_painter;
+};
+
+#endif // MOVIEDELEGATE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviemodel.h"
+
+#include "data/cinemaschedule.h"
+#include "data/movie.h"
+#include "utils/assertedlocker.h"
+
+#include <iostream>
+
+MovieModel::MovieModel(const CinemaSchedule *cinema_schedule, QObject *parent)
+ : QAbstractListModel(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+int MovieModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ return _cinema_schedule->GetMovies().values().size();
+}
+
+QVariant MovieModel::data(const QModelIndex &index, int role) const
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ if (!(index.isValid() && index.row() >= 0 && index.row() < _cinema_schedule->GetMovies().values().size())) {
+ std::cout << "MovieModel: invalid index" << std::endl;
+ return QVariant();
+ }
+ Movie *movie = _cinema_schedule->GetMovies().values().operator [](index.row());
+ if (movie == 0) {
+ std::cout << "movie is 0 (row = " << index.row() << ", size = " << _cinema_schedule->GetMovies().values().size() << ")" << std::endl;
+ return QVariant();
+ }
+ switch (role) {
+ case Qt::DisplayRole:
+ case MovieItemRole:
+ return qVariantFromValue(MovieItem(*movie));
+ case MovieKeyRole:
+ return qVariantFromValue(movie->GetKey());
+ case SortRole:
+ return QVariant(movie->GetName());
+ }
+ return QVariant();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIEMODEL_H
+#define MOVIEMODEL_H
+
+#include "data/movie.h"
+
+#include <QAbstractListModel>
+
+class CinemaSchedule;
+
+class MovieModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum {
+ SortRole = Qt::UserRole,
+ MovieItemRole,
+ MovieKeyRole
+ };
+public:
+ MovieModel(const CinemaSchedule *, QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private:
+ const CinemaSchedule *_cinema_schedule;
+};
+
+class MovieItem
+{
+public:
+ MovieItem() {}
+ MovieItem(const Movie &movie) : _movie(movie) {}
+ const Movie *GetMovie() const { return &_movie; }
+private:
+ Movie _movie;
+};
+
+Q_DECLARE_METATYPE(MovieItem);
+
+
+#endif // MOVIEMODEL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviepainter.h"
+
+#include "data/movie.h"
+#include "ratingprovider.h"
+#include "ui/styleutils.h"
+
+#include <QPainter>
+#include <QStyleOptionViewItem>
+
+MoviePainter::MoviePainter()
+ : _rating_height(RatingProvider::INSTANCE()->GetRating(0.0).height())
+{
+}
+
+void MoviePainter::Paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const Movie *movie) const
+{
+ painter->setFont(option.font);
+ painter->setPen(StyleUtils::INSTANCE()->GetColor(option.palette, StyleUtils::DefaultTextColor));
+ painter->drawText(0, painter->fontMetrics().ascent(), movie->GetName());
+ int y = painter->fontMetrics().height() + 2;
+ int h = option.font.pointSizeF() * 0.7;
+ if (_rating_height > h) {
+ h = _rating_height;
+ }
+ painter->setPen(StyleUtils::INSTANCE()->GetColor(option.palette, StyleUtils::SecondaryTextColor));
+ QRect bounding_rect;
+ bool drawn = false;
+ if (movie->GetDuration().isValid()) {
+ QFont font2(option.font);
+ font2.setPointSizeF(font2.pointSizeF() * 0.7);
+ painter->setFont(font2);
+ int minutes = movie->GetDuration().hour() * 60 + movie->GetDuration().minute();
+ painter->drawText(0, y, 1000, painter->fontMetrics().height(),
+ 0 /* Qt::AlignBottom */, QString(QObject::tr("%1min", "movie duration")).arg(minutes), &bounding_rect);
+ drawn = true;
+ }
+ if (!movie->GetComment().isEmpty()) {
+ QFont font2(option.font);
+ font2.setPointSizeF(font2.pointSizeF() * 0.7);
+ painter->setFont(font2);
+ painter->drawText(bounding_rect.right(), y, 1000, painter->fontMetrics().height(),
+ 0 /* Qt::AlignBottom */, QString(drawn ? ", %1" : "%1").arg(movie->GetComment()), &bounding_rect);
+ drawn = true;
+ }
+ if (movie->GetRate() >= 0.0) {
+ QPixmap p = RatingProvider::INSTANCE()->GetRating(movie->GetRate());
+ painter->drawPixmap(bounding_rect.right() + (drawn ? 8 : 0), y + h - p.height(), p);
+ drawn = true;
+ }
+}
+
+QSize MoviePainter::GetSizeHint(const QStyleOptionViewItem &option) const
+{
+ int y0 = option.fontMetrics.height();
+ int y1 = option.fontMetrics.height() * 0.7;
+ if (_rating_height > y1) {
+ y1 = _rating_height;
+ }
+ return QSize(0, y0 + 2 + y1 + 4);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIEPAINTER_H
+#define MOVIEPAINTER_H
+
+#include <QSize>
+
+class QPainter;
+class QStyleOptionViewItem;
+class Movie;
+
+class MoviePainter
+{
+public:
+ MoviePainter();
+
+ void Paint(QPainter *painter, const QStyleOptionViewItem &option, const Movie *movie) const;
+
+ QSize GetSizeHint(const QStyleOptionViewItem &option) const;
+
+private:
+ int _rating_height;
+};
+
+#endif // MOVIEPAINTER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviescheduledelegate.h"
+
+#include "movieschedulemodel.h"
+#include "data/scheduleentry.h"
+#include "data/cinema.h"
+#include "scheduleentryitem.h"
+#include "utils/timeutils.h"
+#include "ui/styleutils.h"
+
+#include <QPainter>
+
+MovieScheduleDelegate::MovieScheduleDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void MovieScheduleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<ScheduleEntryItem>(index.data())) {
+ ScheduleEntryItem item = qVariantValue<ScheduleEntryItem>(index.data());
+ painter->save();
+ painter->translate(option.rect.x(), option.rect.y());
+ if (item.IsScheduleDateItem()) {
+ _day_painter.Paint(painter, option, item.GetScheduleDate());
+ } else {
+ QRect bounding_rect;
+ QFont bigfont(option.font);
+ bigfont.setPointSizeF(bigfont.pointSizeF() * 1.5);
+ painter->setFont(bigfont);
+ painter->setPen(StyleUtils::INSTANCE()->GetScheduleTimeColor(option.palette, item.GetScheduleEntry()->GetStartTime()));
+ painter->drawText(0, 0, 1000, option.rect.height() - 4,
+ Qt::AlignTop, TimeUtils::ToTimeString(item.GetScheduleEntry()->GetStartTime()), &bounding_rect);
+ int x = bounding_rect.right() + 8;
+ painter->translate(x, 0);
+ _cinema_painter.Paint(painter, option, item.GetScheduleEntry()->GetCinema());
+ }
+ painter->restore();
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize MovieScheduleDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<ScheduleEntryItem>(index.data())) {
+ ScheduleEntryItem item = qVariantValue<ScheduleEntryItem>(index.data());
+ if (item.IsScheduleDateItem()) {
+ return _day_painter.GetSizeHint(option);
+ }
+ return _cinema_painter.GetSizeHint(option);
+ } else {
+ return QStyledItemDelegate::sizeHint(option, index);
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIESCHEDULEDELEGATE_H
+#define MOVIESCHEDULEDELEGATE_H
+
+#include "cinemapainter.h"
+#include "daypainter.h"
+
+#include <QStyledItemDelegate>
+
+class QModelIndex;
+
+class MovieScheduleDelegate : public QStyledItemDelegate
+{
+public:
+ MovieScheduleDelegate(QWidget *parent = 0);
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private:
+ CinemaPainter _cinema_painter;
+ DayPainter _day_painter;
+};
+
+#endif // MOVIESCHEDULEDELEGATE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "movieschedulemodel.h"
+
+#include "scheduleentryitem.h"
+#include "data/cinemaschedule.h"
+#include "utils/assertedlocker.h"
+
+#include <iostream>
+
+MovieScheduleModel::MovieScheduleModel(const CinemaSchedule *cinema_schedule, const MovieKey &movie_key, QObject *parent)
+ : QAbstractListModel(parent),
+ _cinema_schedule(cinema_schedule),
+ _movie_key(movie_key)
+{
+}
+
+void MovieScheduleModel::Update()
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Movie *movie = _cinema_schedule->FindMovie(_movie_key);
+ if (movie != 0) {
+ _schedule_dates = _cinema_schedule->GetScheduleDates(movie).toList();
+ _schedule_keys = _cinema_schedule->GetScheduleKeys(movie->GetKey()).toList();
+ }
+}
+
+int MovieScheduleModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return _schedule_dates.size() + _schedule_keys.size();
+}
+
+QVariant MovieScheduleModel::data(const QModelIndex &index, int role) const
+{
+ if (!(index.isValid() && index.row() >= 0 && index.row() < _schedule_dates.size() + _schedule_keys.size())) {
+ std::cout << "MovieScheduleModel: invalid index" << std::endl;
+ return QVariant();
+ }
+ if (index.row() < _schedule_dates.size()) {
+ QDate date = _schedule_dates[index.row()];
+ switch (role) {
+ case Qt::DisplayRole:
+ return qVariantFromValue(ScheduleEntryItem(date));
+ case SortRole:
+ return QVariant(date.toString("yyyyMMdd"));
+ }
+ } else {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const ScheduleEntryKey &schedule_entry_key = _schedule_keys.operator [](index.row() - _schedule_dates.size());
+ const ScheduleEntry schedule_entry = _cinema_schedule->FindScheduleEntry(schedule_entry_key);
+ if (schedule_entry.IsValid()) {
+ switch (role) {
+ case Qt::DisplayRole:
+ case MovieScheduleItemRole:
+ return qVariantFromValue(ScheduleEntryItem(schedule_entry));
+ case MovieScheduleKeyRole:
+ return qVariantFromValue(schedule_entry_key);
+ case SortRole:
+ return QVariant(schedule_entry.GetDate().toString("yyyyMMdd") + schedule_entry.GetStartTime().toString("hhmm")
+ + schedule_entry.GetCinema()->GetName());
+ }
+ }
+ }
+ return QVariant();
+}
+
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIESCHEDULEMODEL_H
+#define MOVIESCHEDULEMODEL_H
+
+#include "data/scheduleentrykey.h"
+#include "data/moviekey.h"
+
+#include <QAbstractListModel>
+
+class CinemaSchedule;
+
+class MovieScheduleModel : public QAbstractListModel
+{
+ Q_OBJECT
+private:
+ typedef QList<QDate> ScheduleDates;
+ typedef QList<ScheduleEntryKey> ScheduleKeys;
+public:
+ enum {
+ SortRole = Qt::UserRole,
+ MovieScheduleItemRole,
+ MovieScheduleKeyRole
+ };
+public:
+ MovieScheduleModel(const CinemaSchedule *, const MovieKey &, QObject *parent = 0);
+
+ void Update();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private:
+ const CinemaSchedule *_cinema_schedule;
+ MovieKey _movie_key;
+ ScheduleDates _schedule_dates;
+ ScheduleKeys _schedule_keys;
+};
+
+#endif // MOVIESCHEDULEMODEL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "moviewindow.h"
+#include "ui_moviewindow.h"
+
+#include "moviescheduledelegate.h"
+#include "movieschedulemodel.h"
+#include "data/cinemaschedule.h"
+
+#include <QStackedLayout>
+#ifdef Q_WS_MAEMO_5
+#include <QAbstractKineticScroller>
+#endif
+
+MovieWindow::MovieWindow(CinemaSchedule *cinema_schedule, QWidget *parent) :
+ AbstractMainWindow(parent),
+ ui(new Ui::MovieWindow),
+ _cinema_schedule(cinema_schedule),
+ _movie_schedule_model(0)
+{
+ ui->setupUi(this);
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+ QStackedLayout *layout = dynamic_cast<QStackedLayout*>(ui->MainStack->layout());
+ if (layout != 0) {
+ layout->setStackingMode(QStackedLayout::StackAll);
+ }
+ QFont f(font());
+ f.setPointSizeF(f.pointSizeF() * 1.5);
+ ui->ErrorMessage->setFont(f);
+ ui->Schedule->setItemDelegate(new MovieScheduleDelegate(this));
+ ui->Schedule->setProperty("FingerScrollable", true);
+ connect(ui->Schedule, SIGNAL(clicked(QModelIndex)), this, SLOT(ScheduleEntrySelected(QModelIndex)));
+}
+
+MovieWindow::~MovieWindow()
+{
+ delete ui;
+}
+
+void MovieWindow::SetMovieName(QString movie_name)
+{
+ ui->Background->SetLabelText(movie_name);
+}
+
+void MovieWindow::SetMovieScheduleModel(QAbstractItemModel *movie_schedule_model)
+{
+ _movie_schedule_model = movie_schedule_model;
+ ui->MoviePages->setCurrentWidget(ui->MoviePage);
+ ui->Schedule->setModel(_movie_schedule_model);
+}
+
+void MovieWindow::SetError(QString error_text)
+{
+ ui->MoviePages->setCurrentWidget(ui->ErrorPage);
+ ui->ErrorMessage->setText(error_text);
+}
+
+bool MovieWindow::IsIdle()
+{
+#ifdef Q_WS_MAEMO_5
+ QAbstractKineticScroller *k1 = ui->Schedule->property("kineticScroller").value<QAbstractKineticScroller *>();
+ bool k1_idle = (k1 == 0) || (k1->state() == QAbstractKineticScroller::Inactive);
+ return k1_idle;
+#else
+ return true;
+#endif
+}
+
+void MovieWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void MovieWindow::ScheduleEntrySelected(QModelIndex index)
+{
+ QVariant var = _movie_schedule_model->data(index, MovieScheduleModel::MovieScheduleKeyRole);
+ ScheduleEntryKey schedule_entry_key = qVariantValue<ScheduleEntryKey>(var);
+ emit ScheduleEntrySelected(schedule_entry_key);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MOVIEWINDOW_H
+#define MOVIEWINDOW_H
+
+#include "abstractmainwindow.h"
+#include "data/scheduleentrykey.h"
+
+#include <QModelIndex>
+
+class CinemaSchedule;
+class QAbstractItemModel;
+
+namespace Ui {
+ class MovieWindow;
+}
+
+class MovieWindow : public AbstractMainWindow {
+ Q_OBJECT
+public:
+ explicit MovieWindow(CinemaSchedule *cinema_schedule, QWidget *parent = 0);
+ ~MovieWindow();
+
+public:
+ Q_SLOT void SetMovieName(QString movie_name);
+ Q_SLOT void SetMovieScheduleModel(QAbstractItemModel *movie_schedule_model);
+ Q_SLOT void SetError(QString error_text);
+
+ bool IsIdle();
+
+public:
+ Q_SIGNAL void ScheduleEntrySelected(ScheduleEntryKey);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Q_SLOT void ScheduleEntrySelected(QModelIndex);
+
+private:
+ Ui::MovieWindow *ui;
+ CinemaSchedule *_cinema_schedule;
+ QAbstractItemModel *_movie_schedule_model;
+};
+
+#endif // MOVIEWINDOW_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MovieWindow</class>
+ <widget class="QMainWindow" name="MovieWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Movie</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="MainStack">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <widget class="QWidget" name="contentsPage">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="MoviePages">
+ <property name="styleSheet">
+ <string notr="true">QListView {
+ background: rgba(255, 255, 255, 0)
+}
+QLabel {
+ background: rgba(255, 255, 255, 0)
+}</string>
+ </property>
+ <widget class="QWidget" name="MoviePage">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="Schedule">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="ErrorPage">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="ErrorMessage">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="backgroundPage">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="BackgroundLabel" name="Background" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>BackgroundLabel</class>
+ <extends>QWidget</extends>
+ <header>ui/backgroundlabel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "ratingprovider.h"
+
+#include <QPixmap>
+
+RatingProvider::RatingProvider()
+{
+ _instance = this;
+}
+
+void RatingProvider::Load()
+{
+ /*
+ The files loaded here are created from files in svg format under license
+ Creative Commons Attribution-Share Alike 2.5 Generic from author "Andreas 06"
+ on commons.wikimedia.org/wiki.
+ */
+ _rating_stars.reserve(11);
+ for (int i = 0; i < 10; ++i) {
+ _rating_stars.append(QPixmap(QString(":/resources/%1.png").arg(i)));
+ }
+}
+
+QPixmap RatingProvider::GetRating(double percentage)
+{
+ if (percentage < 0.0 || percentage > 1.0) {
+ return QPixmap();
+ }
+ return _rating_stars[(int) (percentage * 10.0)];
+}
+
+RatingProvider *RatingProvider::_instance;
+
+RatingSingleton::RatingSingleton()
+{
+ _instance.Load();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef RATINGPROVIDER_H
+#define RATINGPROVIDER_H
+
+#include <QVector>
+
+class QPixmap;
+
+class RatingProvider
+{
+ friend class RatingSingleton;
+private:
+ RatingProvider();
+
+public:
+ static RatingProvider *INSTANCE() { return _instance; }
+ QPixmap GetRating(double percentage);
+
+private:
+ void Load();
+
+private:
+ static RatingProvider *_instance;
+ QVector<QPixmap> _rating_stars;
+};
+
+class RatingSingleton
+{
+public:
+ RatingSingleton();
+
+private:
+ RatingProvider _instance;
+};
+
+#endif // RATINGPROVIDER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "scheduleentryitem.h"
+
+ScheduleEntryItem::ScheduleEntryItem() :
+ _is_schedule_date_item(false)
+{
+}
+
+ScheduleEntryItem::ScheduleEntryItem(QDate schedule_date) :
+ _is_schedule_date_item(true),
+ _schedule_date(schedule_date)
+{
+}
+
+ScheduleEntryItem::ScheduleEntryItem(const ScheduleEntry &schedule_entry) :
+ _is_schedule_date_item(false),
+ _schedule_entry(schedule_entry),
+ _movie(*schedule_entry.GetMovie()),
+ _cinema(*schedule_entry.GetCinema())
+{
+ _schedule_entry.SetMovie(&_movie);
+ _schedule_entry.SetCinema(&_cinema);
+}
+
+ScheduleEntryItem::ScheduleEntryItem(const ScheduleEntryItem &rhs) :
+ _is_schedule_date_item(rhs._is_schedule_date_item),
+ _schedule_date(rhs._schedule_date),
+ _schedule_entry(rhs._schedule_entry),
+ _movie(rhs._movie),
+ _cinema(rhs._cinema)
+{
+ _schedule_entry.SetMovie(&_movie);
+ _schedule_entry.SetCinema(&_cinema);
+}
+
+ScheduleEntryItem &ScheduleEntryItem::operator= (const ScheduleEntryItem &rhs)
+{
+ if (this != &rhs) {
+ _is_schedule_date_item = rhs._is_schedule_date_item;
+ _schedule_date = rhs._schedule_date;
+ _schedule_entry = rhs._schedule_entry;
+ _movie = rhs._movie;
+ _cinema = rhs._cinema;
+ _schedule_entry.SetMovie(&_movie);
+ _schedule_entry.SetCinema(&_cinema);
+ }
+ return *this;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SCHEDULEENTRYITEM_H
+#define SCHEDULEENTRYITEM_H
+
+#include "data/scheduleentry.h"
+#include "data/cinema.h"
+#include "data/movie.h"
+
+#include <QMetaType>
+
+class ScheduleEntryItem {
+public:
+ ScheduleEntryItem();
+ ScheduleEntryItem(QDate schedule_date);
+ ScheduleEntryItem(const ScheduleEntry &schedule_entry);
+ ScheduleEntryItem(const ScheduleEntryItem &);
+ ScheduleEntryItem &operator=(const ScheduleEntryItem &);
+ bool IsScheduleDateItem() const { return _is_schedule_date_item; }
+ QDate GetScheduleDate() const { return _schedule_date; }
+ const ScheduleEntry *GetScheduleEntry() const { return &_schedule_entry; }
+private:
+ bool _is_schedule_date_item;
+ QDate _schedule_date;
+ ScheduleEntry _schedule_entry;
+ Movie _movie;
+ Cinema _cinema;
+};
+
+Q_DECLARE_METATYPE(ScheduleEntryItem);
+
+#endif // SCHEDULEENTRYITEM_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "styleutils.h"
+
+#ifdef Q_WS_MAEMO_5
+#include <QMaemo5Style>
+#endif
+
+#include <QPalette>
+
+StyleUtils::StyleUtils()
+{
+}
+
+QColor StyleUtils::GetColor(const QPalette &palette, StandardColor standard_color)
+{
+#ifdef Q_WS_MAEMO_5
+ Q_UNUSED(palette);
+ switch (standard_color)
+ {
+ case DefaultBackgroundColor:
+ return QMaemo5Style::standardColor("DefaultBackgroundColor");
+ case DefaultTextColor:
+ return QMaemo5Style::standardColor("DefaultTextColor");
+ case SecondaryTextColor:
+ return QMaemo5Style::standardColor("ActiveTextColor");
+ default:
+ return QColor();
+ }
+#else
+ QColor color;
+ switch (standard_color)
+ {
+ case DefaultBackgroundColor:
+ return palette.color(QPalette::Window);
+ case DefaultTextColor:
+ return palette.color(QPalette::WindowText);
+ case SecondaryTextColor:
+ color = palette.color(QPalette::WindowText);
+ color.setAlpha(160);
+ return color;
+ default:
+ return palette.color(QPalette::WindowText);
+ }
+#endif
+}
+
+QColor StyleUtils::GetScheduleTimeColor(const QPalette &palette, QTime time)
+{
+ Q_UNUSED(time);
+#ifdef Q_WS_MAEMO_5
+ return QMaemo5Style::standardColor("DefaultTextColor");
+#else
+ QColor color = palette.color(QPalette::WindowText);
+ return color;
+#endif
+}
+
+QColor StyleUtils::GetDayTextColor(const QPalette &palette, const QDate &date)
+{
+ Q_UNUSED(date);
+#ifdef Q_WS_MAEMO_5
+ QColor color = QMaemo5Style::standardColor("DefaultTextColor");
+ color.setAlpha(160);
+ return color;
+#else
+ QColor color = palette.color(QPalette::WindowText);
+ color.setAlpha(160);
+ return color;
+#endif
+}
+
+QColor StyleUtils::GetDayBackgroundColor(const QPalette &palette, const QDate &date)
+{
+ Q_UNUSED(date);
+#ifdef Q_WS_MAEMO_5
+ QColor color = QMaemo5Style::standardColor("DefaultTextColor");
+ color.setAlpha(48);
+ return color;
+#else
+ QColor color = palette.color(QPalette::WindowText);
+ color.setAlpha(48);
+ return color;
+#endif
+}
+
+StyleUtils *StyleUtils::_instance = 0;
+
+StyleUtilsSingleton::StyleUtilsSingleton()
+{
+ StyleUtils::_instance = &_instance;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef STYLEUTILS_H
+#define STYLEUTILS_H
+
+#include <QColor>
+#include <QTime>
+#include <QDate>
+
+class QPalette;
+
+class StyleUtils
+{
+ friend class StyleUtilsSingleton;
+
+public:
+ enum StandardColor {
+ DefaultBackgroundColor,
+ DefaultTextColor,
+ SecondaryTextColor
+ };
+
+ enum Font {
+ TextFont,
+ SecondaryTextFont,
+ };
+
+private:
+ StyleUtils();
+
+public:
+ QColor GetColor(const QPalette &palette, StandardColor standard_color);
+
+ QColor GetScheduleTimeColor(const QPalette &palette, QTime time);
+
+ QColor GetDayTextColor(const QPalette &palette, const QDate &date);
+
+ QColor GetDayBackgroundColor(const QPalette &palette, const QDate &date);
+
+public:
+ static StyleUtils *INSTANCE() { return _instance; }
+
+private:
+ static StyleUtils *_instance;
+};
+
+class StyleUtilsSingleton
+{
+public:
+ StyleUtilsSingleton();
+
+private:
+ StyleUtils _instance;
+};
+
+#endif // STYLEUTILS_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theaterdelegate.h"
+
+#include "theatermodel.h"
+#include "data/cinema.h"
+
+#include <QPainter>
+
+TheaterDelegate::TheaterDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void TheaterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<TheaterItem>(index.data())) {
+ TheaterItem item = qVariantValue<TheaterItem>(index.data());
+ painter->save();
+ painter->translate(option.rect.x(), option.rect.y());
+ _cinema_painter.Paint(painter, option, item.GetCinema());
+ painter->restore();
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize TheaterDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<TheaterItem>(index.data())) {
+ return _cinema_painter.GetSizeHint(option);
+ } else {
+ return QStyledItemDelegate::sizeHint(option, index);
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERDELEGATE_H
+#define THEATERDELEGATE_H
+
+#include "cinemapainter.h"
+
+#include <QStyledItemDelegate>
+
+class TheaterDelegate : public QStyledItemDelegate
+{
+public:
+ TheaterDelegate(QWidget *parent = 0);
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private:
+ CinemaPainter _cinema_painter;
+};
+
+#endif // THEATERDELEGATE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theatermodel.h"
+
+#include "data/cinemaschedule.h"
+#include "data/cinema.h"
+#include "utils/assertedlocker.h"
+
+#include <iostream>
+
+TheaterModel::TheaterModel(const CinemaSchedule *cinema_schedule, QObject *parent)
+ : QAbstractListModel(parent),
+ _cinema_schedule(cinema_schedule)
+{
+}
+
+int TheaterModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ return _cinema_schedule->GetCinemas().values().size();
+}
+
+QVariant TheaterModel::data(const QModelIndex &index, int role) const
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ if (!(index.isValid() && index.row() >= 0 && index.row() < _cinema_schedule->GetCinemas().values().size())) {
+ std::cout << "TheaterModel: invalid index" << std::endl;
+ return QVariant();
+ }
+ Cinema *cinema = _cinema_schedule->GetCinemas().values().operator [](index.row());
+ if (cinema == 0) {
+ std::cout << "cinema is 0 (row = " << index.row() << ", size = " << _cinema_schedule->GetCinemas().values().size() << ")" << std::endl;
+ return QVariant();
+ }
+ //std::cout << "row = " << index.row() << " role = " << role << std::endl;
+ switch (role) {
+ case Qt::DisplayRole:
+ case TheaterItemRole:
+ return qVariantFromValue(TheaterItem(*cinema));
+ case TheaterKeyRole:
+ return qVariantFromValue(cinema->GetKey());
+ case SortRole:
+ return QVariant(cinema->GetName());
+ }
+ return QVariant();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERMODEL_H
+#define THEATERMODEL_H
+
+#include "data/cinema.h"
+
+#include <QString>
+#include <QAbstractListModel>
+
+class CinemaSchedule;
+class Cinema;
+
+class TheaterModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum {
+ SortRole = Qt::UserRole,
+ TheaterItemRole,
+ TheaterKeyRole
+ };
+public:
+ TheaterModel(const CinemaSchedule *, QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private:
+ const CinemaSchedule *_cinema_schedule;
+};
+
+class TheaterItem
+{
+public:
+ TheaterItem() {}
+ TheaterItem(const Cinema &cinema) : _cinema(cinema) {}
+ const Cinema *GetCinema() const { return &_cinema; }
+private:
+ Cinema _cinema;
+};
+
+Q_DECLARE_METATYPE(TheaterItem);
+
+#endif // THEATERMODEL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theaterscheduledelegate.h"
+
+#include "theaterschedulemodel.h"
+#include "data/scheduleentry.h"
+#include "data/movie.h"
+#include "scheduleentryitem.h"
+#include "utils/timeutils.h"
+#include "ui/styleutils.h"
+
+#include <QPainter>
+
+TheaterScheduleDelegate::TheaterScheduleDelegate(QWidget *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void TheaterScheduleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<ScheduleEntryItem>(index.data())) {
+ ScheduleEntryItem item = qVariantValue<ScheduleEntryItem>(index.data());
+ painter->save();
+ painter->translate(option.rect.x(), option.rect.y());
+ QRect bounding_rect;
+ QFont bigfont(option.font);
+ bigfont.setPointSizeF(bigfont.pointSizeF() * 1.5);
+ painter->setFont(bigfont);
+ if (item.IsScheduleDateItem()) {
+ _day_painter.Paint(painter, option, item.GetScheduleDate());
+ } else {
+ painter->setPen(StyleUtils::INSTANCE()->GetScheduleTimeColor(option.palette, item.GetScheduleEntry()->GetStartTime()));
+ painter->drawText(0, 0, 1000, option.rect.height() - 4,
+ Qt::AlignTop, TimeUtils::ToTimeString(item.GetScheduleEntry()->GetStartTime()), &bounding_rect);
+ int x = bounding_rect.right() + 8;
+ painter->translate(x, 0);
+ _movie_painter.Paint(painter, option, item.GetScheduleEntry()->GetMovie());
+ }
+ painter->restore();
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize TheaterScheduleDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (qVariantCanConvert<ScheduleEntryItem>(index.data())) {
+ ScheduleEntryItem item = qVariantValue<ScheduleEntryItem>(index.data());
+ if (item.IsScheduleDateItem()) {
+ return _day_painter.GetSizeHint(option);
+ }
+ return _movie_painter.GetSizeHint(option);
+ } else {
+ return QStyledItemDelegate::sizeHint(option, index);
+ }
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERSCHEDULEDELEGATE_H
+#define THEATERSCHEDULEDELEGATE_H
+
+#include "moviepainter.h"
+#include "daypainter.h"
+
+#include <QStyledItemDelegate>
+
+class TheaterScheduleDelegate : public QStyledItemDelegate
+{
+public:
+ TheaterScheduleDelegate(QWidget *parent = 0);
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private:
+ MoviePainter _movie_painter;
+ DayPainter _day_painter;
+};
+
+#endif // THEATERSCHEDULEDELEGATE_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theaterschedulemodel.h"
+
+#include "scheduleentryitem.h"
+#include "data/cinemaschedule.h"
+#include "utils/assertedlocker.h"
+
+#include <iostream>
+
+TheaterScheduleModel::TheaterScheduleModel(const CinemaSchedule *cinema_schedule, const CinemaKey &cinema_key, QObject *parent)
+ : QAbstractListModel(parent),
+ _cinema_schedule(cinema_schedule),
+ _cinema_key(cinema_key)
+{
+}
+
+void TheaterScheduleModel::Update()
+{
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const Cinema *cinema = _cinema_schedule->FindCinema(_cinema_key);
+ if (cinema != 0) {
+ _schedule_dates = _cinema_schedule->GetScheduleDates(cinema).toList();
+ _schedule_keys = _cinema_schedule->GetScheduleKeys(_cinema_key).toList();
+ }
+}
+
+int TheaterScheduleModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return _schedule_dates.size() + _schedule_keys.size();
+}
+
+QVariant TheaterScheduleModel::data(const QModelIndex &index, int role) const
+{
+ if (!(index.isValid() && index.row() >= 0 && index.row() < _schedule_dates.size() + _schedule_keys.size())) {
+ std::cout << "TheaterScheduleModel: invalid index" << std::endl;
+ return QVariant();
+ }
+ if (index.row() < _schedule_dates.size()) {
+ QDate date = _schedule_dates[index.row()];
+ switch (role) {
+ case Qt::DisplayRole:
+ return qVariantFromValue(ScheduleEntryItem(date));
+ case SortRole:
+ return QVariant(date.toString("yyyyMMdd"));
+ }
+ } else {
+ AssertedReadLocker locker(_cinema_schedule->GetLock());
+ const ScheduleEntryKey &schedule_entry_key = _schedule_keys.operator [](index.row() - _schedule_dates.size());
+ const ScheduleEntry schedule_entry = _cinema_schedule->FindScheduleEntry(schedule_entry_key);
+ if (schedule_entry.IsValid()) {
+ switch (role) {
+ case Qt::DisplayRole:
+ case TheaterScheduleItemRole:
+ return qVariantFromValue(ScheduleEntryItem(schedule_entry));
+ case TheaterScheduleKeyRole:
+ return qVariantFromValue(schedule_entry_key);
+ case SortRole:
+ return QVariant(schedule_entry.GetDate().toString("yyyyMMdd") + schedule_entry.GetStartTime().toString("hhmm")
+ + schedule_entry.GetMovie()->GetName());
+ }
+ }
+ }
+ return QVariant();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERSCHEDULEMODEL_H
+#define THEATERSCHEDULEMODEL_H
+
+#include "data/scheduleentrykey.h"
+#include "data/cinema.h"
+#include "data/movie.h"
+#include "data/scheduleentry.h"
+
+#include <QAbstractListModel>
+
+class CinemaSchedule;
+
+class TheaterScheduleModel : public QAbstractListModel
+{
+ Q_OBJECT
+private:
+ typedef QList<QDate> ScheduleDates;
+ typedef QList<ScheduleEntryKey> ScheduleKeys;
+public:
+ enum {
+ SortRole = Qt::UserRole,
+ TheaterScheduleItemRole,
+ TheaterScheduleKeyRole
+ };
+public:
+ TheaterScheduleModel(const CinemaSchedule *, const CinemaKey &, QObject *parent = 0);
+
+ void Update();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private:
+ const CinemaSchedule *_cinema_schedule;
+ CinemaKey _cinema_key;
+ ScheduleDates _schedule_dates;
+ ScheduleKeys _schedule_keys;
+};
+
+#endif // THEATERSCHEDULEMODEL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "theaterwindow.h"
+#include "ui_theaterwindow.h"
+
+#include "theaterscheduledelegate.h"
+#include "theaterschedulemodel.h"
+#include "data/cinemaschedule.h"
+
+#include <QStackedLayout>
+#ifdef Q_WS_MAEMO_5
+#include <QAbstractKineticScroller>
+#endif
+
+TheaterWindow::TheaterWindow(CinemaSchedule *cinema_schedule, QWidget *parent) :
+ AbstractMainWindow(parent),
+ ui(new Ui::TheaterWindow),
+ _cinema_schedule(cinema_schedule),
+ _theater_schedule_model(0)
+{
+ ui->setupUi(this);
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+#endif
+ QStackedLayout *layout = dynamic_cast<QStackedLayout*>(ui->MainStack->layout());
+ if (layout != 0) {
+ layout->setStackingMode(QStackedLayout::StackAll);
+ }
+ QFont f(font());
+ f.setPointSizeF(f.pointSizeF() * 1.5);
+ ui->ErrorMessage->setFont(f);
+ ui->Schedule->setItemDelegate(new TheaterScheduleDelegate(this));
+ ui->Schedule->setProperty("FingerScrollable", true);
+ connect(ui->Schedule, SIGNAL(clicked(QModelIndex)), this, SLOT(ScheduleEntrySelected(QModelIndex)));
+}
+
+TheaterWindow::~TheaterWindow()
+{
+ delete ui;
+}
+
+void TheaterWindow::SetTheaterName(QString movie_name)
+{
+ ui->Background->SetLabelText(movie_name);
+}
+
+void TheaterWindow::SetTheaterScheduleModel(QAbstractItemModel *theater_schedule_model)
+{
+ _theater_schedule_model = theater_schedule_model;
+ ui->TheaterPages->setCurrentWidget(ui->TheaterPage);
+ ui->Schedule->setModel(_theater_schedule_model);
+}
+
+void TheaterWindow::SetError(QString error_text)
+{
+ ui->TheaterPages->setCurrentWidget(ui->ErrorPage);
+ ui->ErrorMessage->setText(error_text);
+}
+
+bool TheaterWindow::IsIdle()
+{
+#ifdef Q_WS_MAEMO_5
+ QAbstractKineticScroller *k1 = ui->Schedule->property("kineticScroller").value<QAbstractKineticScroller *>();
+ bool k1_idle = (k1 == 0) || (k1->state() == QAbstractKineticScroller::Inactive);
+ return k1_idle;
+#else
+ return true;
+#endif
+}
+
+void TheaterWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void TheaterWindow::ScheduleEntrySelected(QModelIndex index)
+{
+ QVariant var = _theater_schedule_model->data(index, TheaterScheduleModel::TheaterScheduleKeyRole);
+ ScheduleEntryKey schedule_entry_key = qVariantValue<ScheduleEntryKey>(var);
+ emit ScheduleEntrySelected(schedule_entry_key);
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef THEATERWINDOW_H
+#define THEATERWINDOW_H
+
+#include "abstractmainwindow.h"
+#include "data/scheduleentrykey.h"
+
+#include <QModelIndex>
+
+class CinemaSchedule;
+class QAbstractItemModel;
+
+namespace Ui {
+ class TheaterWindow;
+}
+
+class TheaterWindow : public AbstractMainWindow {
+ Q_OBJECT
+public:
+ explicit TheaterWindow(CinemaSchedule *cinema_schedule, QWidget *parent = 0);
+ ~TheaterWindow();
+
+public:
+ Q_SLOT void SetTheaterName(QString theater_name);
+ Q_SLOT void SetTheaterScheduleModel(QAbstractItemModel *theater_schedule_model);
+ Q_SLOT void SetError(QString error_text);
+
+ bool IsIdle();
+
+public:
+ Q_SIGNAL void ScheduleEntrySelected(ScheduleEntryKey);
+
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Q_SLOT void ScheduleEntrySelected(QModelIndex);
+
+private:
+ Ui::TheaterWindow *ui;
+ CinemaSchedule *_cinema_schedule;
+ QAbstractItemModel *_theater_schedule_model;
+};
+
+#endif // THEATERWINDOW_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TheaterWindow</class>
+ <widget class="QMainWindow" name="TheaterWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Theater</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="MainStack">
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <widget class="QWidget" name="contentsPage">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="TheaterPages">
+ <property name="styleSheet">
+ <string notr="true">QListView {
+ background: rgba(255, 255, 255, 0)
+}
+QLabel {
+ background: rgba(255, 255, 255, 0)
+}</string>
+ </property>
+ <widget class="QWidget" name="TheaterPage">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="Schedule">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="ErrorPage">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="ErrorMessage">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="backgroundPage">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="BackgroundLabel" name="Background" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>BackgroundLabel</class>
+ <extends>QWidget</extends>
+ <header>ui/backgroundlabel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "uiutils.h"
+
+#ifdef Q_WS_MAEMO_5
+#include <QMaemo5InformationBox>
+#else
+#include <QMessageBox>
+#endif
+
+UiUtils::UiUtils()
+{
+}
+
+void UiUtils::ShowInformation(const QString &infomsg)
+{
+#ifdef Q_WS_MAEMO_5
+ QMaemo5InformationBox::information(0, infomsg, QMaemo5InformationBox::NoTimeout);
+#else
+ QMessageBox::information(0, "Movie-Schedule", infomsg);
+#endif
+}
+
+void UiUtils::ShowError(const QString &errormsg)
+{
+#ifdef Q_WS_MAEMO_5
+ QMaemo5InformationBox::information(0, errormsg, QMaemo5InformationBox::NoTimeout);
+#else
+ QMessageBox::critical(0, "Movie-Schedule", errormsg);
+#endif
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef UIUTILS_H
+#define UIUTILS_H
+
+#include <QString>
+
+class UiUtils
+{
+private:
+ UiUtils();
+
+public:
+
+ static void ShowInformation(const QString &infomsg);
+
+ static void ShowError(const QString &errormsg);
+
+};
+
+#endif // UIUTILS_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "assertedlock.h"
+
+#include <QMutexLocker>
+#include <QThread>
+
+AssertedLock::AssertedLock()
+ :
+#ifndef NDEBUG
+ _lock_counter(0),
+ _mutex(),
+#endif
+ _lock(QReadWriteLock::Recursive)
+{
+}
+
+AssertedLock::~AssertedLock()
+{
+#ifndef NDEBUG
+ QMutexLocker locker(&_mutex);
+ Q_ASSERT_X(_lock_counter == 0, __func__, "lock counter must be 0");
+#endif
+}
+
+void AssertedLock::Lock(LockMode mode)
+{
+#ifndef NDEBUG
+ {
+ QMutexLocker locker(&_mutex);
+ if (GetLockCounter() > 0) {
+ if (GetLockMode() == READ) {
+ if (mode != READ) {
+ Q_ASSERT_X(mode == READ, __func__, "unable to change lockmode from READ to WRITE");
+ }
+ } else {
+ if (mode != WRITE) {
+ mode = WRITE;
+ }
+ }
+ } else {
+ SetLockMode(mode);
+ }
+ IncLockCounter();
+ }
+#endif
+ if (mode == READ) {
+ _lock.lockForRead();
+ } else {
+ _lock.lockForWrite();
+ }
+}
+
+void AssertedLock::Unlock()
+{
+#ifndef NDEBUG
+ {
+ QMutexLocker locker(&_mutex);
+ Q_ASSERT_X(GetLockCounter() > 0, __func__, "too many unlocks");
+ DecLockCounter();
+ }
+#endif
+ _lock.unlock();
+}
+
+#ifndef NDEBUG
+AssertedLock::LockMode AssertedLock::GetLockMode() const
+{
+ return _thread_data[QThread::currentThread()]._lock_mode;
+}
+
+void AssertedLock::SetLockMode(LockMode mode)
+{
+ _thread_data[QThread::currentThread()]._lock_mode = mode;
+}
+
+int AssertedLock::GetLockCounter() const
+{
+ return _thread_data[QThread::currentThread()]._lock_counter;
+}
+
+void AssertedLock::IncLockCounter()
+{
+ _thread_data[QThread::currentThread()]._lock_counter += 1;
+ ++_lock_counter;
+}
+
+void AssertedLock::DecLockCounter()
+{
+ _thread_data[QThread::currentThread()]._lock_counter -= 1;
+ --_lock_counter;
+}
+
+void AssertedLock::AssertLockedForMode(LockMode mode) const
+{
+ QMutexLocker locker(&_mutex);
+ if (GetLockCounter() <= 0) {
+ Q_ASSERT_X(_lock_counter > 0, __func__, "expected lock");
+ }
+ if (GetLockMode() == READ) {
+ if (mode != READ) {
+ Q_ASSERT_X(mode == READ, __func__, "locked for READ but WRITE lock expected");
+ }
+ }
+}
+
+void AssertedLock::AssertNotLocked() const
+{
+ QMutexLocker locker(&_mutex);
+ Q_ASSERT_X(GetLockCounter() == 0, __func__, "unexpected lock.");
+}
+#endif
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ASSERTEDLOCK_H
+#define ASSERTEDLOCK_H
+
+#include <QMutex>
+#include <QReadWriteLock>
+#include <QMap>
+
+class QThread;
+
+class AssertedLock
+{
+public:
+ enum LockMode { READ, WRITE };
+
+#ifndef NDEBUG
+private:
+ struct LockData {
+ LockData() : _lock_mode(READ), _lock_counter(0) {}
+ LockMode _lock_mode;
+ int _lock_counter;
+ };
+
+ typedef QMap<QThread*, LockData> ThreadData;
+#endif
+
+public:
+ AssertedLock();
+ ~AssertedLock();
+
+ void Lock(LockMode mode);
+ void LockForRead() { Lock(READ); }
+ void LockForWrite() { Lock(WRITE); }
+
+ void Unlock();
+
+ void AssertLockedForRead() const
+ {
+#ifndef DEBUG
+ AssertLockedForMode(READ);
+#endif
+ }
+
+ void AssertLockedForWrite() const
+ {
+#ifndef NDEBUG
+ AssertLockedForMode(WRITE);
+#endif
+ }
+
+ void AssertUnlocked() const
+ {
+#ifndef NDEBUG
+ AssertNotLocked();
+#endif
+ }
+
+#ifndef NDEBUG
+private:
+ LockMode GetLockMode() const;
+ void SetLockMode(LockMode mode);
+ int GetLockCounter() const;
+ void IncLockCounter();
+ void DecLockCounter();
+ void AssertLockedForMode(LockMode mode) const;
+ void AssertNotLocked() const;
+#endif
+
+private:
+#ifndef NDEBUG
+ int _lock_counter;
+ ThreadData _thread_data;
+ mutable QMutex _mutex;
+#endif
+ QReadWriteLock _lock;
+};
+
+#endif // ASSERTEDLOCK_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "assertedlocker.h"
+
+#include "assertedlock.h"
+
+AssertedLocker::AssertedLocker(AssertedLock *lock, LockMode mode)
+ : _lock(lock)
+{
+ _lock->Lock(mode == READ ? AssertedLock::READ : AssertedLock::WRITE);
+}
+
+AssertedLocker::~AssertedLocker()
+{
+ _lock->Unlock();
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ASSERTEDLOCKER_H
+#define ASSERTEDLOCKER_H
+
+class AssertedLock;
+
+class AssertedLocker
+{
+public:
+ enum LockMode { READ, WRITE };
+
+public:
+ AssertedLocker(AssertedLock *, LockMode mode);
+ ~AssertedLocker();
+
+private:
+ AssertedLock *_lock;
+};
+
+class AssertedReadLocker : public AssertedLocker
+{
+public:
+ AssertedReadLocker(AssertedLock *lock) : AssertedLocker(lock, READ) {}
+};
+
+class AssertedWriteLocker : public AssertedLocker
+{
+public:
+ AssertedWriteLocker(AssertedLock *lock) : AssertedLocker(lock, WRITE) {}
+};
+
+#endif // ASSERTEDLOCKER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "asynccall.h"
+
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ASYNCCALL_H
+#define ASYNCCALL_H
+
+#include "asynccallclient.h"
+#include "asynccallproxy.h"
+
+namespace AsyncCallPrivate {
+
+ template<class OBJECT, typename METHOD>
+ class AsyncCall0 : public CallProxyBase
+ {
+ public:
+ AsyncCall0(OBJECT *object, const METHOD &method)
+ : _object(object),
+ _method(method)
+ {
+ }
+
+ void CallClient()
+ {
+ AsyncCallClient *client = new AsyncCallClient(_object->thread());
+ client->Call(this);
+ }
+
+ virtual void Call()
+ {
+ (_object->*_method)();
+ }
+
+ private:
+ OBJECT *_object;
+ METHOD _method;
+ };
+
+ template<class OBJECT, typename METHOD, typename ARG1>
+ class AsyncCall1 : public CallProxyBase
+ {
+ public:
+ AsyncCall1(OBJECT *object, const METHOD &method, const ARG1 &arg1)
+ : _object(object),
+ _method(method),
+ _arg1(arg1)
+ {
+ }
+
+ void CallClient()
+ {
+ AsyncCallClient *client = new AsyncCallClient(_object->thread());
+ client->Call(this);
+ }
+
+ virtual void Call()
+ {
+ (_object->*_method)(_arg1);
+ }
+
+ private:
+ OBJECT *_object;
+ METHOD _method;
+ ARG1 _arg1;
+ };
+
+ template<class OBJECT, typename METHOD, typename ARG1, typename ARG2>
+ class AsyncCall2 : public CallProxyBase
+ {
+ public:
+ AsyncCall2(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2)
+ : _object(object),
+ _method(method),
+ _arg1(arg1),
+ _arg2(arg2)
+ {
+ }
+
+ void CallClient()
+ {
+ AsyncCallClient *client = new AsyncCallClient(_object->thread());
+ client->Call(this);
+ }
+
+ virtual void Call()
+ {
+ (_object->*_method)(_arg1, _arg2);
+ }
+
+ private:
+ OBJECT *_object;
+ METHOD _method;
+ ARG1 _arg1;
+ ARG2 _arg2;
+ };
+
+ template<class OBJECT, typename METHOD, typename ARG1, typename ARG2, typename ARG3>
+ class AsyncCall3 : public CallProxyBase
+ {
+ public:
+ AsyncCall3(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3)
+ : _object(object),
+ _method(method),
+ _arg1(arg1),
+ _arg2(arg2),
+ _arg3(arg3)
+ {
+ }
+
+ void CallClient()
+ {
+ AsyncCallClient *client = new AsyncCallClient(_object->thread());
+ client->Call(this);
+ }
+
+ virtual void Call()
+ {
+ (_object->*_method)(_arg1, _arg2, _arg3);
+ }
+
+ private:
+ OBJECT *_object;
+ METHOD _method;
+ ARG1 _arg1;
+ ARG2 _arg2;
+ ARG3 _arg3;
+ };
+
+ template<class OBJECT, typename METHOD, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
+ class AsyncCall4 : public CallProxyBase
+ {
+ public:
+ AsyncCall4(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3, const ARG4 &arg4)
+ : _object(object),
+ _method(method),
+ _arg1(arg1),
+ _arg2(arg2),
+ _arg3(arg3),
+ _arg4(arg4)
+ {
+ }
+
+ void CallClient()
+ {
+ AsyncCallClient *client = new AsyncCallClient(_object->thread());
+ client->Call(this);
+ }
+
+ virtual void Call()
+ {
+ (_object->*_method)(_arg1, _arg2, _arg3, _arg4);
+ }
+
+ private:
+ OBJECT *_object;
+ METHOD _method;
+ ARG1 _arg1;
+ ARG2 _arg2;
+ ARG3 _arg3;
+ ARG4 _arg4;
+ };
+}
+
+template<class OBJECT, typename METHOD>
+void CallAsync(OBJECT *object, const METHOD &method)
+{
+ AsyncCallPrivate::AsyncCall0<OBJECT, METHOD> *async_call = new AsyncCallPrivate::AsyncCall0<OBJECT, METHOD>(object, method);
+ async_call->CallClient();
+}
+
+template<class OBJECT, typename METHOD, typename ARG1>
+void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1)
+{
+ AsyncCallPrivate::AsyncCall1<OBJECT, METHOD, ARG1> *async_call = new AsyncCallPrivate::AsyncCall1<OBJECT, METHOD, ARG1>(object, method, arg1);
+ async_call->CallClient();
+}
+
+template<class OBJECT, typename METHOD, typename ARG1, typename ARG2>
+void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2)
+{
+ AsyncCallPrivate::AsyncCall2<OBJECT, METHOD, ARG1, ARG2> *async_call = new AsyncCallPrivate::AsyncCall2<OBJECT, METHOD, ARG1, ARG2>(object, method, arg1, arg2);
+ async_call->CallClient();
+}
+
+template<class OBJECT, typename METHOD, typename ARG1, typename ARG2, typename ARG3>
+void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3)
+{
+ AsyncCallPrivate::AsyncCall3<OBJECT, METHOD, ARG1, ARG2, ARG3> *async_call = new AsyncCallPrivate::AsyncCall3<OBJECT, METHOD, ARG1, ARG2, ARG3>(object, method, arg1, arg2, arg3);
+ async_call->CallClient();
+}
+
+template<class OBJECT, typename METHOD, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
+void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3, const ARG4 &arg4)
+{
+ AsyncCallPrivate::AsyncCall4<OBJECT, METHOD, ARG1, ARG2, ARG3, ARG4> *async_call = new AsyncCallPrivate::AsyncCall4<OBJECT, METHOD, ARG1, ARG2, ARG3, ARG4>(object, method, arg1, arg2, arg3, arg4);
+ async_call->CallClient();
+}
+
+#endif // ASYNCCALL_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "asynccallclient.h"
+
+#include "asynccallproxy.h"
+
+namespace AsyncCallPrivate {
+
+ AsyncCallClient::AsyncCallClient(QThread *proxy_thread, QObject *parent) :
+ QObject(parent),
+ _proxy(new AsyncCallProxy(0))
+ {
+ connect(this, SIGNAL(CallAsync(CallProxyBase*)), _proxy, SLOT(Call(CallProxyBase*)));
+ _proxy->moveToThread(proxy_thread);
+ }
+
+ void AsyncCallClient::Call(CallProxyBase *call_proxy_base)
+ {
+ emit CallAsync(call_proxy_base);
+ deleteLater();
+ }
+
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ASYNCCALLCLIENT_H
+#define ASYNCCALLCLIENT_H
+
+#include <QObject>
+
+namespace AsyncCallPrivate {
+
+ class CallProxyBase;
+ class AsyncCallProxy;
+
+ class AsyncCallClient : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ explicit AsyncCallClient(QThread *proxy_thread, QObject *parent = 0);
+
+ public:
+ void Call(CallProxyBase *);
+
+ private:
+ Q_SIGNAL void CallAsync(CallProxyBase *);
+
+ private:
+ AsyncCallProxy *_proxy;
+ };
+}
+
+#endif // ASYNCCALLCLIENT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "asynccallproxy.h"
+
+#include <QtGlobal>
+
+namespace AsyncCallPrivate {
+
+ CallProxyBase::CallProxyBase()
+ {
+ }
+
+ CallProxyBase::~CallProxyBase()
+ {
+ }
+
+ void CallProxyBase::Call()
+ {
+ Q_ASSERT_X(false, __func__, "missing implementation");
+ }
+
+ AsyncCallProxy::AsyncCallProxy(QObject *parent) :
+ QObject(parent)
+ {
+ }
+
+ void AsyncCallProxy::Call(CallProxyBase *call_proxy_base)
+ {
+ call_proxy_base->Call();
+ delete call_proxy_base;
+ deleteLater();
+ }
+
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef ASYNCCALLPROXY_H
+#define ASYNCCALLPROXY_H
+
+#include <QObject>
+
+namespace AsyncCallPrivate {
+
+ class CallProxyBase {
+ template<class OBJECT, typename METHOD> friend class AsyncCall0;
+ template<class OBJECT, typename METHOD, typename ARG1> friend class AsyncCall1;
+ template<class OBJECT, typename METHOD, typename ARG1, typename ARG2> friend class AsyncCall2;
+
+ protected:
+ CallProxyBase();
+
+ public:
+ virtual ~CallProxyBase();
+
+ public:
+ virtual void Call();
+ };
+
+ class AsyncCallProxy : public QObject
+ {
+ Q_OBJECT
+ public:
+ explicit AsyncCallProxy(QObject *parent = 0);
+
+ public:
+ Q_SLOT void Call(CallProxyBase *);
+
+ };
+
+}
+
+#endif // ASYNCCALLPROXY_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "calendar.h"
+
+#ifdef MAEMO_SDK
+#include <CCalendar.h>
+#include <CMulticalendar.h>
+#include <CEvent.h>
+#include <CalendarErrors.h>
+
+Calendar::Calendar(QObject *parent)
+ : QObject(parent),
+ _multi_calendar(0)
+{
+ _multi_calendar = CMulticalendar::MCInstance();
+}
+
+Calendar::~Calendar()
+{
+ delete _multi_calendar;
+}
+
+bool Calendar::AddEvent(const QString &event_name, const QDateTime &start_time,
+ const QDateTime &end_time, const QString &location, const QString &description)
+{
+ int error_code = 0;
+
+ CCalendar *calendar = _multi_calendar->getDefaultCalendar();
+ if (calendar == 0) {
+ return false;
+ }
+ CEvent *event = new CEvent(event_name.toStdString(), description.toStdString(),
+ location.toStdString(), start_time.toTime_t(), end_time.toTime_t());
+ event->setAlarmBefore(3600);
+ if (!calendar->addEvent(event, error_code)) {
+ return false;
+ }
+ delete event;
+ if (error_code != CALENDAR_ENTRY_DUPLICATED && error_code != CALENDAR_OPERATION_SUCCESSFUL) {
+ return false;
+ }
+ return true;
+}
+#endif
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CALENDAR_H
+#define CALENDAR_H
+
+#ifdef MAEMO_SDK
+
+#include <QObject>
+#include <QDateTime>
+
+class CMulticalendar;
+
+class Calendar : public QObject
+{
+ Q_OBJECT
+
+public:
+ Calendar(QObject *parent = 0);
+ ~Calendar();
+
+ bool AddEvent(const QString &event_name,
+ const QDateTime &start_time, const QDateTime &end_time,
+ const QString &location, const QString &description);
+private:
+ CMulticalendar *_multi_calendar;
+};
+
+#endif
+
+#endif // CALENDAR_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CONNECT_H
+#define CONNECT_H
+
+#include <QObject>
+
+namespace xQt {
+
+ enum ExtendedConnectionType {
+ AutoConnection = Qt::AutoConnection,
+ DirectConnection = Qt::DirectConnection,
+ QueuedConnection = Qt::QueuedConnection,
+ BlockingQueuedConnection = Qt::BlockingQueuedConnection,
+ UniqueConnection = Qt::UniqueConnection,
+ AutoBlockingConnection = 40,
+ };
+
+ inline void connect(QObject *sender, const char *signal, QObject *receiver, const char *method, ExtendedConnectionType type)
+ {
+ switch (type) {
+ // TODO support UniqueConnection flag
+ case AutoBlockingConnection:
+ QObject::connect(sender, signal, receiver, method,
+ (sender->thread() == receiver->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection);
+ break;
+ default:
+ QObject::connect(sender, signal, receiver, method, (Qt::ConnectionType) type);
+ break;
+ }
+ }
+}
+
+#endif // CONNECT_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "connectivitymanager.h"
+
+#include <QDBusMessage>
+#include <QDBusInterface>
+#ifdef MAEMO_SDK
+#include <icd/dbus_api.h>
+#endif
+
+ConnectivityManager::ConnectivityManager(QObject *parent)
+ : QObject(parent),
+ _dbus_connection(QDBusConnection::systemBus()),
+#ifdef MAEMO_SDK
+ _interface(new QDBusInterface(ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_PATH,
+ ICD_DBUS_API_INTERFACE,
+ _dbus_connection))
+#else
+ _interface(0)
+#endif
+{
+#ifdef MAEMO_SDK
+ _dbus_connection.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_STATISTICS_SIG, this, SLOT(StatisticsSentResult(const QDBusMessage&)));
+ _dbus_connection.connect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_STATE_SIG, this, SLOT(ChangeState(const QDBusMessage&)));
+#endif
+}
+
+ConnectivityManager::~ConnectivityManager()
+{
+#ifdef MAEMO_SDK
+ _dbus_connection.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_STATE_SIG, this, SLOT(ChangeState(const QDBusMessage&)));
+ _dbus_connection.disconnect(ICD_DBUS_API_INTERFACE, ICD_DBUS_API_PATH, ICD_DBUS_API_INTERFACE,
+ ICD_DBUS_API_STATISTICS_SIG, this, SLOT(StatisticsSentResult(const QDBusMessage&)));
+#endif
+}
+
+void ConnectivityManager::Connect()
+{
+#ifdef MAEMO_SDK
+ _interface->call(ICD_DBUS_API_CONNECT_REQ,
+ QVariant((unsigned int) ICD_CONNECTION_FLAG_USER_EVENT));
+#endif
+ UpdateConnectionState();
+}
+
+void ConnectivityManager::Disconnect()
+{
+#ifdef MAEMO_SDK
+ _interface->call(ICD_DBUS_API_DISCONNECT_REQ,
+ QVariant((unsigned int) ICD_CONNECTION_FLAG_USER_EVENT));
+#endif
+}
+
+void ConnectivityManager::UpdateConnectionState()
+{
+#ifdef MAEMO_SDK
+ _interface->call(ICD_DBUS_API_STATE_REQ);
+#endif
+ emit Connected();
+}
+
+void ConnectivityManager::StatisticsSentResult(const QDBusMessage &rep)
+{
+ Q_UNUSED(rep);
+}
+
+void ConnectivityManager::ChangeState(const QDBusMessage &rep)
+{
+#ifdef MAEMO_SDK
+ QString connection_error = rep.arguments().value(6).value<QString>();
+
+ if (!connection_error.isEmpty()) {
+ emit Error();
+ return;
+ }
+
+ unsigned int connection_status = rep.arguments().value(7).value<unsigned int>();
+
+ switch (connection_status) {
+ case ICD_STATE_DISCONNECTED:
+ emit Disconnected();
+ break;
+ case ICD_STATE_CONNECTING:
+ break;
+ case ICD_STATE_CONNECTED:
+ emit Connected();
+ break;
+ case ICD_STATE_DISCONNECTING:
+ break;
+ case ICD_STATE_LIMITED_CONN_ENABLED:
+ break;
+ case ICD_STATE_LIMITED_CONN_DISABLED:
+ break;
+ case ICD_STATE_SEARCH_START:
+ break;
+ case ICD_STATE_SEARCH_STOP:
+ break;
+ case ICD_STATE_INTERNAL_ADDRESS_ACQUIRED:
+ break;
+ }
+#else
+ Q_UNUSED(rep);
+#endif
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef CONNECTIVITYMANAGER_H
+#define CONNECTIVITYMANAGER_H
+
+#include <QObject>
+#include <QDBusConnection>
+
+class QDBusMessage;
+class QDBusInterface;
+
+class ConnectivityManager : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ConnectivityManager(QObject *parent = 0);
+ ~ConnectivityManager();
+
+public:
+ Q_SLOT void Connect();
+ Q_SLOT void Disconnect();
+ Q_SLOT void UpdateConnectionState();
+
+public:
+ Q_SIGNAL void Connected();
+ Q_SIGNAL void Disconnected();
+ Q_SIGNAL void Error();
+
+private:
+ Q_SLOT void StatisticsSentResult(const QDBusMessage& rep);
+ Q_SLOT void ChangeState(const QDBusMessage& rep);
+
+private:
+ QDBusConnection _dbus_connection;
+ QDBusInterface *_interface;
+};
+
+#endif // CONNECTIVITYMANAGER_H
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#include "timeutils.h"
+
+TimeUtils::TimeUtils()
+{
+}
+
+QTime TimeUtils::FromTimeString(const QString &time)
+{
+ int pos = 0;
+ int n = time.length();
+ int hours = 0;
+ int minutes = 0;
+ int m = 0;
+ while (pos < n && time[pos].isDigit()) {
+ hours = 10 * hours + time[pos].digitValue();
+ ++pos;
+ ++m;
+ }
+ if (m == 0 || pos >= n || time[pos] != ':') {
+ return QTime();
+ }
+ ++pos;
+ m = 0;
+ while (pos < n && time[pos].isDigit()) {
+ minutes = 10 * minutes + time[pos].digitValue();
+ ++pos;
+ ++m;
+ }
+ if (m == 0) {
+ return QTime();
+ }
+ if (pos < n) {
+ QString s = time.mid(pos);
+ if (s.compare("pm", Qt::CaseInsensitive) == 0) {
+ if (hours < 12) {
+ hours += 12;
+ }
+ } else if (s.compare("am", Qt::CaseInsensitive) == 0) {
+ // nothing to do
+ } else {
+ return QTime();
+ }
+ } else {
+ // assume pm as default
+ if (hours < 12) {
+ hours += 12;
+ }
+ }
+ return QTime(hours, minutes);
+}
+
+QString TimeUtils::ToTimeString(const QTime &time)
+{
+ QString s = time.toString(Qt::SystemLocaleShortDate);
+ return s;
+}
+
+QString TimeUtils::ToDateString(const QDate &date)
+{
+ QString date_name;
+ if (date == QDate::currentDate()) {
+ date_name = QObject::tr("Today", "DayPainter");
+ } else if (date == QDate::currentDate().addDays(1)) {
+ date_name = QObject::tr("Tomorrow", "DayPainter");
+ } else {
+ date_name = date.toString("dddd");
+ }
+ return date_name;
+}
--- /dev/null
+// Copyright 2010 Jochen Becher
+//
+// This file is part of MovieSchedule.
+//
+// MovieSchedule 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.
+//
+// MovieSchedule 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 MovieSchedule. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef TIMEUTILS_H
+#define TIMEUTILS_H
+
+#include <QString>
+#include <QTime>
+#include <QDate>
+
+class TimeUtils
+{
+private:
+ TimeUtils();
+
+public:
+ static QTime FromTimeString(const QString &time);
+
+ static QString ToTimeString(const QTime &time);
+
+ static QString ToDateString(const QDate &date);
+};
+
+#endif // TIMEUTILS_H