From: gilead Date: Sun, 8 Aug 2010 17:07:00 +0000 (+0200) Subject: Merge https://vcs.maemo.org/git/movie-schedule X-Git-Url: http://git.maemo.org/git/?p=movie-schedule;a=commitdiff_plain;h=2198ae3ccdffc8b6495ee1f5f91657611808ec93;hp=2fb68d8c6ff890dece1073d7ae9056e626efa0ec Merge https://vcs.maemo.org/git/movie-schedule --- diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..10926e8 --- /dev/null +++ b/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/README b/README new file mode 100644 index 0000000..b44a61c --- /dev/null +++ b/README @@ -0,0 +1,36 @@ +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 ). +I would like to coordinate those efforts. + +Regards, Jochen "gilead" Becher + diff --git a/data/48x48/movie-schedule.png b/data/48x48/movie-schedule.png new file mode 100644 index 0000000..c592a83 Binary files /dev/null and b/data/48x48/movie-schedule.png differ diff --git a/data/clap.xcf b/data/clap.xcf new file mode 100644 index 0000000..efb0dc6 Binary files /dev/null and b/data/clap.xcf differ diff --git a/data/movie-schedule.desktop b/data/movie-schedule.desktop new file mode 100644 index 0000000..594288b --- /dev/null +++ b/data/movie-schedule.desktop @@ -0,0 +1,12 @@ +[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 diff --git a/data/scalable/movie-schedule.png b/data/scalable/movie-schedule.png new file mode 100644 index 0000000..8462162 Binary files /dev/null and b/data/scalable/movie-schedule.png differ diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c9e0f24 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,13 @@ +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 Thu, 08 Aug 2010 17:15:00 +0000 + +movie-schedule (0.1.0) unstable; urgency=low + + * Initial release (Closes: #0000) + + -- Jochen Becher Mon, 31 May 2010 23:50:29 +0000 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..0d8ed11 --- /dev/null +++ b/debian/control @@ -0,0 +1,66 @@ +Source: movie-schedule +Section: user/network +Priority: optional +Maintainer: Jochen Becher +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== diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..8eb02e4 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,20 @@ +This package was debianized by Jochen Becher 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 . + diff --git a/debian/optify b/debian/optify new file mode 100644 index 0000000..588192d --- /dev/null +++ b/debian/optify @@ -0,0 +1,2 @@ +auto + diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 0000000..81f432b --- /dev/null +++ b/debian/postinst @@ -0,0 +1,6 @@ +#!/bin/sh -e + +gtk-update-icon-cache -f /usr/share/icons/hicolor + +exit 0 + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..9863b42 --- /dev/null +++ b/debian/rules @@ -0,0 +1,57 @@ +#!/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 + diff --git a/movie-schedule.pro b/movie-schedule.pro new file mode 100644 index 0000000..df2e2e7 --- /dev/null +++ b/movie-schedule.pro @@ -0,0 +1,8 @@ +QMAKEVERSION = $$[QMAKE_VERSION] +ISQT4 = $$find(QMAKEVERSION, ^[2-9]) +isEmpty( ISQT4 ) { + error("Use the qmake include with Qt4.4 or greater."); +} + +TEMPLATE = subdirs +SUBDIRS = src diff --git a/movie-schedule.pro.user (Example) b/movie-schedule.pro.user (Example) new file mode 100644 index 0000000..73ca508 --- /dev/null +++ b/movie-schedule.pro.user (Example) @@ -0,0 +1,421 @@ + + + + ProjectExplorer.Project.ActiveTarget + 2 + + + ProjectExplorer.Project.EditorSettings + + System + + + + ProjectExplorer.Project.Target.0 + + Maemo + Qt4ProjectManager.Target.MaemoDeviceTarget + 1 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + CONFIG+=mobility + + + + Make + Qt4ProjectManager.MakeStep + false + + + + + + Qt4ProjectManager.MaemoPackageCreationStep + + true + /usr/local/bin/movie-schedule + + + 3 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-arm-debug-madde + 3 + 9 + true + + + + + sb-conf + select + FREMANTLE_ARMEL + + /scratchbox/login + true + $BUILDDIR + Select Target + ProjectExplorer.ProcessStep + + + + -d + Movies/movie-schedule-arm-debug-sdk + qmake + ../movie-schedule/movie-schedule.pro + -r + -spec + linux-g++ + CONFIG+=maemo_sdk + CONFIG+=debug + + /scratchbox/login + true + $BUILDDIR + QMake + ProjectExplorer.ProcessStep + + + + -d + Movies/movie-schedule-arm-debug-sdk + make + -w + + /scratchbox/login + true + $BUILDDIR + Make + ProjectExplorer.ProcessStep + + 3 + + + -d + Movies/movie-schedule-arm-debug-sdk + make + -w + clean + + /scratchbox/login + true + $BUILDDIR + Clean + ProjectExplorer.ProcessStep + + 1 + false + + Debug (SDK) + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-arm-debug-sdk + 3 + 9 + true + + 2 + + src/src.pro + N900 + Qt4ProjectManager.MaemoRunConfiguration + + + 1 + + + + src/src.pro + N900 Emulator + Qt4ProjectManager.MaemoRunConfiguration + + + 9 + + + 2 + + + + ProjectExplorer.Project.Target.1 + + Qt Simulator + Qt4ProjectManager.Target.QtSimulatorTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + CONFIG+=mobility + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-simulator + 2 + 0 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-build-simulator + 2 + 0 + true + + 2 + + src + Qt4ProjectManager.Qt4RunConfiguration + 2 + + src/src.pro + false + false + + false + false + + + 1 + + + + ProjectExplorer.Project.Target.2 + + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-desktop + 8 + 0 + true + + + + + sb-conf + select + FREMANTLE_X86 + + /scratchbox/login + true + $BUILDDIR + Select Target + ProjectExplorer.ProcessStep + + + + mkdir + -p + Movies/movie-schedule-x86-debug-sdk + + /scratchbox/login + true + $BUILDDIR + Create Builddir + ProjectExplorer.ProcessStep + + + + -d + Movies/movie-schedule-x86-debug-sdk + qmake + ../movie-schedule/movie-schedule.pro + -r + -spec + linux-g++ + CONFIG+=maemo_sdk + CONFIG+=debug + + /scratchbox/login + true + $BUILDDIR + QMake + ProjectExplorer.ProcessStep + + + + -d + Movies/movie-schedule-x86-debug-sdk + make + -w + + /scratchbox/login + true + $BUILDDIR + Make + ProjectExplorer.ProcessStep + + 4 + + + -d + Movies/movie-schedule-x86-debug-sdk + make + -w + clean + + /scratchbox/login + true + $BUILDDIR + Clean + ProjectExplorer.ProcessStep + + 1 + false + + Debug (SDK) + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-x86-debug-sdk + 8 + 0 + true + + + + + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule/movie-schedule.pro + + lupdate + true + $BUILDDIR + LUpdate + ProjectExplorer.ProcessStep + + 1 + 0 + false + + LUpdate + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /scratchbox/users/jbecher/home/jbecher/Movies/movie-schedule-lupdate + 8 + 0 + true + + 3 + + src + Qt4ProjectManager.Qt4RunConfiguration + 2 + + src/src.pro + false + false + + false + false + + + 1 + + + + ProjectExplorer.Project.TargetCount + 3 + + + ProjectExplorer.Project.Updater.FileVersion + 4 + + diff --git a/src/control/actioncontroller.cpp b/src/control/actioncontroller.cpp new file mode 100644 index 0000000..3d74247 --- /dev/null +++ b/src/control/actioncontroller.cpp @@ -0,0 +1,228 @@ +// 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 . + +#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 +#include +#include +#include + +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 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 ", 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); +} diff --git a/src/control/actioncontroller.h b/src/control/actioncontroller.h new file mode 100644 index 0000000..9c593b9 --- /dev/null +++ b/src/control/actioncontroller.h @@ -0,0 +1,52 @@ +// 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 . + +#ifndef ACTIONCONTROLLER_H +#define ACTIONCONTROLLER_H + +#include "data/cinemakey.h" +#include "data/moviekey.h" +#include "data/scheduleentrykey.h" + +#include + +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 diff --git a/src/control/itemmodelsortclient.cpp b/src/control/itemmodelsortclient.cpp new file mode 100644 index 0000000..efa8775 --- /dev/null +++ b/src/control/itemmodelsortclient.cpp @@ -0,0 +1,51 @@ +// 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 . + +#include "itemmodelsortclient.h" + +#include "itemmodelsortproxy.h" +#include "itemmodelsortcontroller.h" + +#include + +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(); +} diff --git a/src/control/itemmodelsortclient.h b/src/control/itemmodelsortclient.h new file mode 100644 index 0000000..ba96f5d --- /dev/null +++ b/src/control/itemmodelsortclient.h @@ -0,0 +1,52 @@ +// 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 . + +#ifndef ITEMMODELSORTCLIENT_H +#define ITEMMODELSORTCLIENT_H + +#include + +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 diff --git a/src/control/itemmodelsortcontroller.cpp b/src/control/itemmodelsortcontroller.cpp new file mode 100644 index 0000000..cef92b8 --- /dev/null +++ b/src/control/itemmodelsortcontroller.cpp @@ -0,0 +1,36 @@ +// 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 . + +#include "itemmodelsortcontroller.h" + +#include "data/cinemaschedule.h" +#include "utils/assertedlocker.h" + +#include +#include + +ItemModelSortController::ItemModelSortController(CinemaSchedule *cinema_schedule) + : _cinema_schedule(cinema_schedule) +{ +} + +void ItemModelSortController::Sort(QAbstractItemModel *model) +{ + AssertedReadLocker(_cinema_schedule->GetLock()); + model->sort(0); + //sleep(2); +} diff --git a/src/control/itemmodelsortcontroller.h b/src/control/itemmodelsortcontroller.h new file mode 100644 index 0000000..844edec --- /dev/null +++ b/src/control/itemmodelsortcontroller.h @@ -0,0 +1,39 @@ +// 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 . + +#ifndef ITEMMODELSORTCONTROLLER_H +#define ITEMMODELSORTCONTROLLER_H + +#include + +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 diff --git a/src/control/itemmodelsortproxy.cpp b/src/control/itemmodelsortproxy.cpp new file mode 100644 index 0000000..03dbd1e --- /dev/null +++ b/src/control/itemmodelsortproxy.cpp @@ -0,0 +1,32 @@ +// 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 . + +#include "itemmodelsortproxy.h" + +#include "itemmodelsortcontroller.h" + +ItemModelSortProxy::ItemModelSortProxy(ItemModelSortController *controller) + : _controller(controller) +{ +} + +void ItemModelSortProxy::Sort(QAbstractItemModel *model) +{ + _controller->Sort(model); + emit SortFinished(model); + deleteLater(); +} diff --git a/src/control/itemmodelsortproxy.h b/src/control/itemmodelsortproxy.h new file mode 100644 index 0000000..b6fd8ee --- /dev/null +++ b/src/control/itemmodelsortproxy.h @@ -0,0 +1,42 @@ +// 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 . + +#ifndef ITEMMODELSORTPROXY_H +#define ITEMMODELSORTPROXY_H + +#include + +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 diff --git a/src/control/locationcontroller.cpp b/src/control/locationcontroller.cpp new file mode 100644 index 0000000..65b2541 --- /dev/null +++ b/src/control/locationcontroller.cpp @@ -0,0 +1,171 @@ +// 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 . + +#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 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); + } +} diff --git a/src/control/locationcontroller.h b/src/control/locationcontroller.h new file mode 100644 index 0000000..a1ffbb2 --- /dev/null +++ b/src/control/locationcontroller.h @@ -0,0 +1,63 @@ +// 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 . + +#ifndef LOCATIONCONTROLLER_H +#define LOCATIONCONTROLLER_H + +#include "data/location.h" + +#include + +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 diff --git a/src/control/maincontroller.cpp b/src/control/maincontroller.cpp new file mode 100644 index 0000000..5130da7 --- /dev/null +++ b/src/control/maincontroller.cpp @@ -0,0 +1,386 @@ +// 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 . + +#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 +#include + +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(); +} diff --git a/src/control/maincontroller.h b/src/control/maincontroller.h new file mode 100644 index 0000000..30f9f4e --- /dev/null +++ b/src/control/maincontroller.h @@ -0,0 +1,105 @@ +// 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 . + +#ifndef MAINCONTROLLER_H +#define MAINCONTROLLER_H + +#include "data/location.h" +#include "data/settings.h" + +#include + +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 diff --git a/src/control/moviecontroller.cpp b/src/control/moviecontroller.cpp new file mode 100644 index 0000000..3b3b42b --- /dev/null +++ b/src/control/moviecontroller.cpp @@ -0,0 +1,188 @@ +// 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 . + +#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 +#include + +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; + } +} diff --git a/src/control/moviecontroller.h b/src/control/moviecontroller.h new file mode 100644 index 0000000..dab70b0 --- /dev/null +++ b/src/control/moviecontroller.h @@ -0,0 +1,70 @@ +// 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 . + +#ifndef MOVIECONTROLLER_H +#define MOVIECONTROLLER_H + +#include "data/scheduleentrykey.h" +#include "data/moviekey.h" + +#include + +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 diff --git a/src/control/settingscontroller.cpp b/src/control/settingscontroller.cpp new file mode 100644 index 0000000..a5e1188 --- /dev/null +++ b/src/control/settingscontroller.cpp @@ -0,0 +1,168 @@ +// 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 . + +#include "settingscontroller.h" + +#include "data/settings.h" + +#include +#include +#include +#include +#include + +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"; +} diff --git a/src/control/settingscontroller.h b/src/control/settingscontroller.h new file mode 100644 index 0000000..7d7889c --- /dev/null +++ b/src/control/settingscontroller.h @@ -0,0 +1,40 @@ +// 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 . + +#ifndef SETTINGSCONTROLLER_H +#define SETTINGSCONTROLLER_H + +#include + +class Settings; + +class SettingsController +{ +public: + SettingsController(Settings *settings); + + void Load(); + void Save(); + +private: + QString GetSettingsFileName(); + +private: + Settings *_settings; +}; + +#endif // SETTINGSCONTROLLER_H diff --git a/src/control/theatercontroller.cpp b/src/control/theatercontroller.cpp new file mode 100644 index 0000000..21d8db8 --- /dev/null +++ b/src/control/theatercontroller.cpp @@ -0,0 +1,187 @@ +// 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 . + +#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 +#include + +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; + } +} diff --git a/src/control/theatercontroller.h b/src/control/theatercontroller.h new file mode 100644 index 0000000..a74a29d --- /dev/null +++ b/src/control/theatercontroller.h @@ -0,0 +1,71 @@ +// 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 . + +#ifndef THEATERCONTROLLER_H +#define THEATERCONTROLLER_H + +#include "data/scheduleentrykey.h" +#include "data/cinemakey.h" + +#include + +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 diff --git a/src/data/cinema.cpp b/src/data/cinema.cpp new file mode 100644 index 0000000..447e201 --- /dev/null +++ b/src/data/cinema.cpp @@ -0,0 +1,22 @@ +// 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 . + +#include "cinema.h" + +Cinema::Cinema() +{ +} diff --git a/src/data/cinema.h b/src/data/cinema.h new file mode 100644 index 0000000..89234b9 --- /dev/null +++ b/src/data/cinema.h @@ -0,0 +1,53 @@ +// 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 . + +#ifndef CINEMA_H +#define CINEMA_H + +#include "cinemakey.h" + +#include + +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 diff --git a/src/data/cinemakey.cpp b/src/data/cinemakey.cpp new file mode 100644 index 0000000..10ef1f7 --- /dev/null +++ b/src/data/cinemakey.cpp @@ -0,0 +1,37 @@ +// 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 . + +#include "cinemakey.h" + +#include + +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()); +} diff --git a/src/data/cinemakey.h b/src/data/cinemakey.h new file mode 100644 index 0000000..25ea70d --- /dev/null +++ b/src/data/cinemakey.h @@ -0,0 +1,47 @@ +// 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 . + +#ifndef CINEMAKEY_H +#define CINEMAKEY_H + +#include +#include + +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 diff --git a/src/data/cinemaschedule.cpp b/src/data/cinemaschedule.cpp new file mode 100644 index 0000000..76e78a9 --- /dev/null +++ b/src/data/cinemaschedule.cpp @@ -0,0 +1,227 @@ +// 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 . + +#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); +} diff --git a/src/data/cinemaschedule.h b/src/data/cinemaschedule.h new file mode 100644 index 0000000..3a0fd9f --- /dev/null +++ b/src/data/cinemaschedule.h @@ -0,0 +1,87 @@ +// 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 . + +#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 +#include +#include + +class Cinema; +class Movie; + +class CinemaSchedule +{ + Q_DISABLE_COPY(CinemaSchedule); +public: + typedef QHash Cinemas; + typedef QHash Movies; + typedef QSet ScheduleDates; + typedef QSet Schedules; + typedef QSet ScheduleKeys; +public: + CinemaSchedule(); + + AssertedLock *GetLock() const { return const_cast(&_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 diff --git a/src/data/location.cpp b/src/data/location.cpp new file mode 100644 index 0000000..8e23fc4 --- /dev/null +++ b/src/data/location.cpp @@ -0,0 +1,32 @@ +// 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 . + +#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); +} diff --git a/src/data/location.h b/src/data/location.h new file mode 100644 index 0000000..1b697d7 --- /dev/null +++ b/src/data/location.h @@ -0,0 +1,44 @@ +// 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 . + +#ifndef LOCATION_H +#define LOCATION_H + +#include +#include + +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 diff --git a/src/data/movie.cpp b/src/data/movie.cpp new file mode 100644 index 0000000..ba21b84 --- /dev/null +++ b/src/data/movie.cpp @@ -0,0 +1,23 @@ +// 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 . + +#include "movie.h" + +Movie::Movie() + : _rate(-1.0) +{ +} diff --git a/src/data/movie.h b/src/data/movie.h new file mode 100644 index 0000000..4ea2349 --- /dev/null +++ b/src/data/movie.h @@ -0,0 +1,56 @@ +// 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 . + +#ifndef MOVIE_H +#define MOVIE_H + +#include "data/moviekey.h" + +#include +#include + +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 diff --git a/src/data/moviekey.cpp b/src/data/moviekey.cpp new file mode 100644 index 0000000..b02c88d --- /dev/null +++ b/src/data/moviekey.cpp @@ -0,0 +1,35 @@ +// 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 . + +#include "moviekey.h" + +#include + +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()); +} diff --git a/src/data/moviekey.h b/src/data/moviekey.h new file mode 100644 index 0000000..8c85473 --- /dev/null +++ b/src/data/moviekey.h @@ -0,0 +1,43 @@ +// 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 . + +#ifndef MOVIEKEY_H +#define MOVIEKEY_H + +#include +#include + +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 diff --git a/src/data/scheduleentry.cpp b/src/data/scheduleentry.cpp new file mode 100644 index 0000000..0071dff --- /dev/null +++ b/src/data/scheduleentry.cpp @@ -0,0 +1,57 @@ +// 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 . + +#include "scheduleentry.h" + +#include "data/cinema.h" +#include "data/movie.h" + +#include + + +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()); +} diff --git a/src/data/scheduleentry.h b/src/data/scheduleentry.h new file mode 100644 index 0000000..9ea8759 --- /dev/null +++ b/src/data/scheduleentry.h @@ -0,0 +1,62 @@ +// 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 . + +#ifndef SCHEDULEENTRY_H +#define SCHEDULEENTRY_H + +#include "scheduleentrykey.h" + +#include +#include + +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 diff --git a/src/data/scheduleentrykey.cpp b/src/data/scheduleentrykey.cpp new file mode 100644 index 0000000..528ac9c --- /dev/null +++ b/src/data/scheduleentrykey.cpp @@ -0,0 +1,42 @@ +// 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 . + +#include "scheduleentrykey.h" + +#include + +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()); +} diff --git a/src/data/scheduleentrykey.h b/src/data/scheduleentrykey.h new file mode 100644 index 0000000..110af6e --- /dev/null +++ b/src/data/scheduleentrykey.h @@ -0,0 +1,59 @@ +// 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 . + +#ifndef SCHEDULEENTRYKEY_H +#define SCHEDULEENTRYKEY_H + +#include "data/cinemakey.h" +#include "data/moviekey.h" + +#include +#include +#include + +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 diff --git a/src/data/settings.cpp b/src/data/settings.cpp new file mode 100644 index 0000000..6c1528a --- /dev/null +++ b/src/data/settings.cpp @@ -0,0 +1,31 @@ +// 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 . + +#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; +} diff --git a/src/data/settings.h b/src/data/settings.h new file mode 100644 index 0000000..d94c76c --- /dev/null +++ b/src/data/settings.h @@ -0,0 +1,58 @@ +// 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 . + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "location.h" + +#include +#include + +class Settings +{ +public: + typedef QList 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 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..645b755 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,25 @@ +// 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 . + +#include "movieschedule.h" + +int main(int argc, char *argv[]) +{ + MovieSchedule movie_schedule; + int rc = movie_schedule.exec(argc, argv); + return rc; +} diff --git a/src/movieschedule.cpp b/src/movieschedule.cpp new file mode 100644 index 0000000..0063016 --- /dev/null +++ b/src/movieschedule.cpp @@ -0,0 +1,149 @@ +// 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 . + +#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 +#include +#include +#include +#include + +#ifdef MAEMO_SDK +#include +#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(); + + 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; +} diff --git a/src/movieschedule.h b/src/movieschedule.h new file mode 100644 index 0000000..6fee109 --- /dev/null +++ b/src/movieschedule.h @@ -0,0 +1,35 @@ +// 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 . + +#ifndef MOVIESCHEDULE_H +#define MOVIESCHEDULE_H + +#include + +class MovieSchedule : public QObject +{ + Q_OBJECT + +public: + MovieSchedule(); + +public: + int exec(int argc, char *argv[]); + +}; + +#endif // MOVIESCHEDULE_H diff --git a/src/resources.qrc b/src/resources.qrc new file mode 100644 index 0000000..516293a --- /dev/null +++ b/src/resources.qrc @@ -0,0 +1,15 @@ + + + resources/0.png + resources/1.png + resources/2.png + resources/3.png + resources/4.png + resources/5.png + resources/6.png + resources/7.png + resources/8.png + resources/9.png + resources/10.png + + diff --git a/src/resources/0.png b/src/resources/0.png new file mode 100644 index 0000000..88c1cc7 Binary files /dev/null and b/src/resources/0.png differ diff --git a/src/resources/0.svg b/src/resources/0.svg new file mode 100644 index 0000000..bfcf957 --- /dev/null +++ b/src/resources/0.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/1.png b/src/resources/1.png new file mode 100644 index 0000000..45648aa Binary files /dev/null and b/src/resources/1.png differ diff --git a/src/resources/1.svg b/src/resources/1.svg new file mode 100644 index 0000000..9e0a953 --- /dev/null +++ b/src/resources/1.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/src/resources/10.png b/src/resources/10.png new file mode 100644 index 0000000..f337945 Binary files /dev/null and b/src/resources/10.png differ diff --git a/src/resources/10.svg b/src/resources/10.svg new file mode 100644 index 0000000..84048aa --- /dev/null +++ b/src/resources/10.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/2.png b/src/resources/2.png new file mode 100644 index 0000000..41884c2 Binary files /dev/null and b/src/resources/2.png differ diff --git a/src/resources/2.svg b/src/resources/2.svg new file mode 100644 index 0000000..c597cda --- /dev/null +++ b/src/resources/2.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/3.png b/src/resources/3.png new file mode 100644 index 0000000..3a467e4 Binary files /dev/null and b/src/resources/3.png differ diff --git a/src/resources/3.svg b/src/resources/3.svg new file mode 100644 index 0000000..75fc022 --- /dev/null +++ b/src/resources/3.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/src/resources/4.png b/src/resources/4.png new file mode 100644 index 0000000..4e34a64 Binary files /dev/null and b/src/resources/4.png differ diff --git a/src/resources/4.svg b/src/resources/4.svg new file mode 100644 index 0000000..304ea8e --- /dev/null +++ b/src/resources/4.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/5.png b/src/resources/5.png new file mode 100644 index 0000000..b33e5d5 Binary files /dev/null and b/src/resources/5.png differ diff --git a/src/resources/5.svg b/src/resources/5.svg new file mode 100644 index 0000000..76194f1 --- /dev/null +++ b/src/resources/5.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/src/resources/6.png b/src/resources/6.png new file mode 100644 index 0000000..f674182 Binary files /dev/null and b/src/resources/6.png differ diff --git a/src/resources/6.svg b/src/resources/6.svg new file mode 100644 index 0000000..b247ff2 --- /dev/null +++ b/src/resources/6.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/7.png b/src/resources/7.png new file mode 100644 index 0000000..fb87d2e Binary files /dev/null and b/src/resources/7.png differ diff --git a/src/resources/7.svg b/src/resources/7.svg new file mode 100644 index 0000000..4c06c38 --- /dev/null +++ b/src/resources/7.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/src/resources/8.png b/src/resources/8.png new file mode 100644 index 0000000..27acdc1 Binary files /dev/null and b/src/resources/8.png differ diff --git a/src/resources/8.svg b/src/resources/8.svg new file mode 100644 index 0000000..0921cf7 --- /dev/null +++ b/src/resources/8.svg @@ -0,0 +1,32 @@ + + + + + + + + + + diff --git a/src/resources/9.png b/src/resources/9.png new file mode 100644 index 0000000..6f9df0a Binary files /dev/null and b/src/resources/9.png differ diff --git a/src/resources/9.svg b/src/resources/9.svg new file mode 100644 index 0000000..fc46692 --- /dev/null +++ b/src/resources/9.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/src/searchclients/abstractsearchclient.cpp b/src/searchclients/abstractsearchclient.cpp new file mode 100644 index 0000000..dc1219f --- /dev/null +++ b/src/searchclients/abstractsearchclient.cpp @@ -0,0 +1,117 @@ +// 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 . + +#include "abstractsearchclient.h" + +#include +#include + +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; diff --git a/src/searchclients/abstractsearchclient.h b/src/searchclients/abstractsearchclient.h new file mode 100644 index 0000000..2cc45bb --- /dev/null +++ b/src/searchclients/abstractsearchclient.h @@ -0,0 +1,68 @@ +// 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 . + +#ifndef ABSTRACTSEARCHCLIENT_H +#define ABSTRACTSEARCHCLIENT_H + +#include +#include +#include +#include + +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 diff --git a/src/searchclients/gpsclient.cpp b/src/searchclients/gpsclient.cpp new file mode 100644 index 0000000..18752ed --- /dev/null +++ b/src/searchclients/gpsclient.cpp @@ -0,0 +1,247 @@ +// 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 . + +#include "gpsclient.h" + +#ifdef QT_MOBILITY_LOCATION +#include +#endif + +#ifdef LIBLOCATION +#include +#endif + +#include +#include +#include +#include +#include +#include + +#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(""); + if (start >= 0) { + int end = data.indexOf("", 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 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; diff --git a/src/searchclients/gpsclient.h b/src/searchclients/gpsclient.h new file mode 100644 index 0000000..f25ac5b --- /dev/null +++ b/src/searchclients/gpsclient.h @@ -0,0 +1,110 @@ +// 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 . + +#ifndef GPSCLIENT_H +#define GPSCLIENT_H + +#include "searchclientsemaphore.h" + +#include +#include +#include + +class QNetworkAccessManager; + +#ifdef QT_MOBILITY_LOCATION +#include + +QTM_BEGIN_NAMESPACE + class QGeoPositionInfo; +class QGeoPositionInfoSource; +QTM_END_NAMESPACE; + +QTM_USE_NAMESPACE; +#endif + +#ifdef LIBLOCATION +extern "C" { +#include +#include +} +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 diff --git a/src/searchclients/movieschedulesearchclient.cpp b/src/searchclients/movieschedulesearchclient.cpp new file mode 100644 index 0000000..cb2ac42 --- /dev/null +++ b/src/searchclients/movieschedulesearchclient.cpp @@ -0,0 +1,231 @@ +// 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 . + +#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 +#include +#include +#include + +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 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 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; diff --git a/src/searchclients/movieschedulesearchclient.h b/src/searchclients/movieschedulesearchclient.h new file mode 100644 index 0000000..5d3bcf2 --- /dev/null +++ b/src/searchclients/movieschedulesearchclient.h @@ -0,0 +1,59 @@ +// 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 . + +#ifndef MOVIESCHEDULESEARCHCLIENT_H +#define MOVIESCHEDULESEARCHCLIENT_H + +#include "abstractsearchclient.h" +#include "searchclientsemaphore.h" +#include "data/moviekey.h" + +#include +#include +#include +#include +#include + +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 _dates_seen; + QQueue > _date_urls; + static SearchClientSemaphore _semaphore; +}; + +#endif // MOVIESCHEDULESEARCHCLIENT_H diff --git a/src/searchclients/moviesearchclient.cpp b/src/searchclients/moviesearchclient.cpp new file mode 100644 index 0000000..670c569 --- /dev/null +++ b/src/searchclients/moviesearchclient.cpp @@ -0,0 +1,193 @@ +// 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 . + +#include "moviesearchclient.h" + +#include "data/cinemaschedule.h" +#include "data/movie.h" +#include "data/moviekey.h" +#include "utils/assertedlocker.h" + +#include +#include +#include + +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 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; diff --git a/src/searchclients/moviesearchclient.h b/src/searchclients/moviesearchclient.h new file mode 100644 index 0000000..486182b --- /dev/null +++ b/src/searchclients/moviesearchclient.h @@ -0,0 +1,46 @@ +// 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 . + +#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 diff --git a/src/searchclients/searchclientsemaphore.cpp b/src/searchclients/searchclientsemaphore.cpp new file mode 100644 index 0000000..00e1205 --- /dev/null +++ b/src/searchclients/searchclientsemaphore.cpp @@ -0,0 +1,41 @@ +// 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 . + +#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; +} diff --git a/src/searchclients/searchclientsemaphore.h b/src/searchclients/searchclientsemaphore.h new file mode 100644 index 0000000..5846b4f --- /dev/null +++ b/src/searchclients/searchclientsemaphore.h @@ -0,0 +1,39 @@ +// 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 . + +#ifndef SEARCHCLIENTSEMAPHORE_H +#define SEARCHCLIENTSEMAPHORE_H + +#include + +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 diff --git a/src/searchclients/theaterschedulesearchclient.cpp b/src/searchclients/theaterschedulesearchclient.cpp new file mode 100644 index 0000000..7e1d0ce --- /dev/null +++ b/src/searchclients/theaterschedulesearchclient.cpp @@ -0,0 +1,265 @@ +// 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 . + +#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 +#include +#include + +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 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 movie_spans; + QString theaters_url; + double rating = -1.0; + QList 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; diff --git a/src/searchclients/theaterschedulesearchclient.h b/src/searchclients/theaterschedulesearchclient.h new file mode 100644 index 0000000..0556ec2 --- /dev/null +++ b/src/searchclients/theaterschedulesearchclient.h @@ -0,0 +1,58 @@ +// 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 . + +#ifndef THEATERSCHEDULESEARCHCLIENT_H +#define THEATERSCHEDULESEARCHCLIENT_H + +#include "abstractsearchclient.h" +#include "searchclientsemaphore.h" +#include "data/cinemakey.h" + +#include +#include +#include +#include +#include + +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 _dates_seen; + QQueue > _date_urls; + static SearchClientSemaphore _semaphore; +}; + +#endif // THEATERSCHEDULESEARCHCLIENT_H diff --git a/src/searchclients/theatersearchclient.cpp b/src/searchclients/theatersearchclient.cpp new file mode 100644 index 0000000..f4f02dc --- /dev/null +++ b/src/searchclients/theatersearchclient.cpp @@ -0,0 +1,163 @@ +// 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 . + +#include "theatersearchclient.h" + +#include "data/cinemakey.h" +#include "data/cinema.h" +#include "data/cinemaschedule.h" +#include "utils/assertedlocker.h" + +#include +#include + +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; diff --git a/src/searchclients/theatersearchclient.h b/src/searchclients/theatersearchclient.h new file mode 100644 index 0000000..d1c76bf --- /dev/null +++ b/src/searchclients/theatersearchclient.h @@ -0,0 +1,46 @@ +// 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 . + +#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 diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..eb34058 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,228 @@ +#------------------------------------------------- +# +# 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 + +} diff --git a/src/translations/movie-schedule_de.ts b/src/translations/movie-schedule_de.ts new file mode 100644 index 0000000..234d259 --- /dev/null +++ b/src/translations/movie-schedule_de.ts @@ -0,0 +1,319 @@ + + + + + AboutDialog + + + About + Über + + + + MovieSchedule + MovieSchedule + + + + <!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> + <!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> + + + <!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> + <!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> + + + + Contact + Kontakt + + + + Done + Fertig + + + + ActionController + + + + + Adding calendar event failed. + Hinzufügen des Kalendereintrags fehlgeschlagen. + + + + %1 (%2 %3) added to your calendar. + %1 (%2, %3) zum Kalender hinzugefügt. + + + + Unable to call theater by phone: communication bus not available. + Telefonanruf fehlgeschlagen: Keine Kommunikation mit dem Telefon möglich. + + + + Unable to call theater by phone: phone service not available. + Telefonanruf fehlgeschlagen: Telefonfunktion steht nicht zur Verfügung. + + + + Unable to call theater by phone: call failed. + Telefonanruf fehlgeschlagen: Kein Anruf möglich. + + + + Unable to search in web: communication bus not available. + Websuche fehlgeschlagen: Kommunikation mit Browser nicht möglich. + + + + + Unable to search in web: browser service not available. + Websuche fehlgeschlagen: Browser steht nicht zur Verfügung. + + + + ContextDialog + + + Actions + Aktionen + + + + Add to Calendar + Im Kalender eintragen + + + + Call Theater By Phone + Kino anrufen + + + + Find Route to Theater + Weg zum Kino suchen + + + + Search Movie in Web + Film im Web suchen + + + + Search Theater in Web + Kino im Web suchen + + + + LocationController + + + Unable to detect current city. + Die nächste Stadt wurde nicht gefunden. + + + + LocationDialog + + + Location + Ort + + + + Search Near + In der Nähe suchen + + + + City + Stadt + + + + Search + Suchen + + + + MainController + + Unable to access network + Netzwerk steht nicht zur Verfügung. + + + + Unable to access network. + Netzwerk steht nicht zur Verfügung. + + + + No theaters found near %1. + Keine Kinos in der Nähe von %1 gefunden. + + + + No movies found near %1. + Keine Filme in der Nähe von %1 gefunden. + + + + Error on fetching theaters. + Fehler beim Lesen der Kinoliste. + + + + Error on fetching movies. + Fehler beim Lesen der Filmliste. + + + + MainWindow + + + + Movies + Filme + + + + + Theaters + Kinos + + + + Location + Ort + + + + About + Über + + + + Call By Phone + Kino anrufen + + + + Find Route + Weg zum Kino suchen + + + + + Search In Web + Im Web suchen + + + Movie-Schedule + Kinoprogramm + + + + + MovieSchedule + MovieSchedule + + + + MovieController + + + No schedule found for %1. + Kein Kinoprogramm für %1 gefunden. + + + + Error on fetching movie schedule. + Fehler beim Lesen des Kinoprogramms. + + + + MovieWindow + + + Movie + Film + + + + QObject + + + Today + DayPainter + Heute + + + + Tomorrow + DayPainter + Morgen + + + + %1min + movie duration + %1Min + + + + TheaterController + + + No schedule found for %1. + Kein Kinoprogramm für %1 gefunden. + + + + Error on fetching theater schedule. + Fehler beim Lesen des Kinoprogramms. + + + + TheaterWindow + + + Theater + Kino + + + diff --git a/src/ui/aboutdialog.cpp b/src/ui/aboutdialog.cpp new file mode 100644 index 0000000..63e5d6c --- /dev/null +++ b/src/ui/aboutdialog.cpp @@ -0,0 +1,41 @@ +// 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 . + +#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; +} diff --git a/src/ui/aboutdialog.h b/src/ui/aboutdialog.h new file mode 100644 index 0000000..0ea60e9 --- /dev/null +++ b/src/ui/aboutdialog.h @@ -0,0 +1,42 @@ +// 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 . + +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include + +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 diff --git a/src/ui/aboutdialog.ui b/src/ui/aboutdialog.ui new file mode 100644 index 0000000..c3e37f2 --- /dev/null +++ b/src/ui/aboutdialog.ui @@ -0,0 +1,161 @@ + + + AboutDialog + + + + 0 + 0 + 443 + 233 + + + + About + + + + + + + Sans Serif + 22 + 75 + true + + + + MovieSchedule + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + QDialogButtonBox::Cancel + + + + + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 311 + 434 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + + + + 0 + 0 + + + + <!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> + + + Qt::RichText + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + true + + + + + + + + + + + Contact + + + false + + + + + + + Done + + + + + + + + diff --git a/src/ui/abstractmainwindow.cpp b/src/ui/abstractmainwindow.cpp new file mode 100644 index 0000000..83af9ac --- /dev/null +++ b/src/ui/abstractmainwindow.cpp @@ -0,0 +1,38 @@ +// 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 . + +#include "abstractmainwindow.h" + +#include + +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 +} diff --git a/src/ui/abstractmainwindow.h b/src/ui/abstractmainwindow.h new file mode 100644 index 0000000..2a70c68 --- /dev/null +++ b/src/ui/abstractmainwindow.h @@ -0,0 +1,35 @@ +// 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 . + +#ifndef ABSTRACTMAINWINDOW_H +#define ABSTRACTMAINWINDOW_H + +#include +#include + +class AbstractMainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit AbstractMainWindow(QWidget *parent = 0); + +public: + Q_SLOT void SetBusy(bool busy); + +}; + +#endif // ABSTRACTMAINWINDOW_H diff --git a/src/ui/backgroundlabel.cpp b/src/ui/backgroundlabel.cpp new file mode 100644 index 0000000..b9c622b --- /dev/null +++ b/src/ui/backgroundlabel.cpp @@ -0,0 +1,86 @@ +// 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 . + +#include "backgroundlabel.h" + +#include +#include + +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); +} diff --git a/src/ui/backgroundlabel.h b/src/ui/backgroundlabel.h new file mode 100644 index 0000000..1eb2123 --- /dev/null +++ b/src/ui/backgroundlabel.h @@ -0,0 +1,43 @@ +// 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 . + +#ifndef BACKGROUNDLABEL_H +#define BACKGROUNDLABEL_H + +#include + +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 diff --git a/src/ui/cinemapainter.cpp b/src/ui/cinemapainter.cpp new file mode 100644 index 0000000..0740a68 --- /dev/null +++ b/src/ui/cinemapainter.cpp @@ -0,0 +1,56 @@ +// 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 . + +#include "cinemapainter.h" + +#include "data/cinema.h" +#include "ui/styleutils.h" + +#include +#include + +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); +} diff --git a/src/ui/cinemapainter.h b/src/ui/cinemapainter.h new file mode 100644 index 0000000..359efa3 --- /dev/null +++ b/src/ui/cinemapainter.h @@ -0,0 +1,38 @@ +// 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 . + +#ifndef CINEMAPAINTER_H +#define CINEMAPAINTER_H + +#include + +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 diff --git a/src/ui/contextdialog.cpp b/src/ui/contextdialog.cpp new file mode 100644 index 0000000..6122238 --- /dev/null +++ b/src/ui/contextdialog.cpp @@ -0,0 +1,138 @@ +// 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 . + +#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 + +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()); +} diff --git a/src/ui/contextdialog.h b/src/ui/contextdialog.h new file mode 100644 index 0000000..29c724e --- /dev/null +++ b/src/ui/contextdialog.h @@ -0,0 +1,72 @@ +// 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 . + +#ifndef CONTEXTDIALOG_H +#define CONTEXTDIALOG_H + +#include "data/cinemakey.h" +#include "data/moviekey.h" +#include "data/scheduleentrykey.h" + +#include + +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 diff --git a/src/ui/contextdialog.ui b/src/ui/contextdialog.ui new file mode 100644 index 0000000..6a6a64b --- /dev/null +++ b/src/ui/contextdialog.ui @@ -0,0 +1,71 @@ + + + ContextDialog + + + + 0 + 0 + 339 + 105 + + + + Actions + + + + 16 + + + 8 + + + 16 + + + 8 + + + 4 + + + + + Add to Calendar + + + + + + + Call Theater By Phone + + + + + + + Find Route to Theater + + + + + + + Search Movie in Web + + + + + + + Search Theater in Web + + + + + + + + diff --git a/src/ui/daypainter.cpp b/src/ui/daypainter.cpp new file mode 100644 index 0000000..40e506b --- /dev/null +++ b/src/ui/daypainter.cpp @@ -0,0 +1,48 @@ +// 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 . + +#include "daypainter.h" +#include "utils/timeutils.h" +#include "ui/styleutils.h" + +#include +#include +#include + +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); +} diff --git a/src/ui/daypainter.h b/src/ui/daypainter.h new file mode 100644 index 0000000..051cbb3 --- /dev/null +++ b/src/ui/daypainter.h @@ -0,0 +1,38 @@ +// 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 . + +#ifndef DAYPAINTER_H +#define DAYPAINTER_H + +#include + +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 diff --git a/src/ui/locationdialog.cpp b/src/ui/locationdialog.cpp new file mode 100644 index 0000000..095da2b --- /dev/null +++ b/src/ui/locationdialog.cpp @@ -0,0 +1,177 @@ +// 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 . + +#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 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; + } +} diff --git a/src/ui/locationdialog.h b/src/ui/locationdialog.h new file mode 100644 index 0000000..f4d966e --- /dev/null +++ b/src/ui/locationdialog.h @@ -0,0 +1,78 @@ +// 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 . + +#ifndef LOCATIONDIALOG_H +#define LOCATIONDIALOG_H + +#include "data/location.h" + +#include +#include +#include + +class QPushButton; + +namespace Ui { + class LocationDialog; +} + +class LocationDialog : public QDialog { + Q_OBJECT + +public: + typedef QList 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 _location_buttons; +}; + +#endif // LOCATIONDIALOG_H diff --git a/src/ui/locationdialog.ui b/src/ui/locationdialog.ui new file mode 100644 index 0000000..45a5d81 --- /dev/null +++ b/src/ui/locationdialog.ui @@ -0,0 +1,162 @@ + + + LocationDialog + + + + 0 + 0 + 280 + 140 + + + + + 0 + 0 + + + + Location + + + true + + + + 4 + + + 16 + + + 8 + + + 16 + + + 8 + + + + + 4 + + + + + Search Near + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + + false + + + + + + + + + 4 + + + + + City + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Qt::Vertical + + + QDialogButtonBox::Cancel + + + + + + + Search + + + true + + + + + + + + + + diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp new file mode 100644 index 0000000..d78aae4 --- /dev/null +++ b/src/ui/mainwindow.cpp @@ -0,0 +1,213 @@ +// 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 . + +#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 +#include +#ifdef Q_WS_MAEMO_5 +#include +#endif +#include + +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(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(var); + return cinema_key; +} + +MovieKey MainWindow::GetMovie(const QModelIndex &index) +{ + QVariant var = _movie_model->data(index, MovieModel::MovieKeyRole); + MovieKey movie_key = qVariantValue(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); +} diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h new file mode 100644 index 0000000..8a6c3e7 --- /dev/null +++ b/src/ui/mainwindow.h @@ -0,0 +1,96 @@ +// 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 . + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "abstractmainwindow.h" +#include "data/location.h" +#include "data/cinemakey.h" +#include "data/moviekey.h" + +#include + +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 diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui new file mode 100644 index 0000000..1ef8ac3 --- /dev/null +++ b/src/ui/mainwindow.ui @@ -0,0 +1,161 @@ + + + MainWindow + + + + 0 + 0 + 800 + 480 + + + + MovieSchedule + + + + + 4 + + + 16 + + + 8 + + + 16 + + + 8 + + + + + + + 0 + + + 0 + + + + + true + + + QListView { + background: rgba(255, 255, 255, 0) +} +QLabel { + background: rgba(255, 255, 255, 0) +} + + + 2 + + + + + 0 + + + 0 + + + + + + + + QFrame::NoFrame + + + + + + + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + + + + 0 + + + 0 + + + + + + + + Qt::AlignCenter + + + true + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + 0 + 0 + 800 + 23 + + + + + + + BackgroundLabel + QWidget +
ui/backgroundlabel.h
+ 1 +
+
+ + +
diff --git a/src/ui/moviedelegate.cpp b/src/ui/moviedelegate.cpp new file mode 100644 index 0000000..dd1ae70 --- /dev/null +++ b/src/ui/moviedelegate.cpp @@ -0,0 +1,50 @@ +// 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 . + +#include "moviedelegate.h" + +#include "moviemodel.h" + +#include + +MovieDelegate::MovieDelegate(QWidget *parent) + : QStyledItemDelegate(parent) +{ +} + +void MovieDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + MovieItem item = qVariantValue(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(index.data())) { + return _movie_painter.GetSizeHint(option); + } else { + return QStyledItemDelegate::sizeHint(option, index); + } +} diff --git a/src/ui/moviedelegate.h b/src/ui/moviedelegate.h new file mode 100644 index 0000000..2d0e5e5 --- /dev/null +++ b/src/ui/moviedelegate.h @@ -0,0 +1,40 @@ +// 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 . + +#ifndef MOVIEDELEGATE_H +#define MOVIEDELEGATE_H + +#include "moviepainter.h" + +#include + +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 diff --git a/src/ui/moviemodel.cpp b/src/ui/moviemodel.cpp new file mode 100644 index 0000000..0b469dd --- /dev/null +++ b/src/ui/moviemodel.cpp @@ -0,0 +1,61 @@ +// 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 . + +#include "moviemodel.h" + +#include "data/cinemaschedule.h" +#include "data/movie.h" +#include "utils/assertedlocker.h" + +#include + +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(); +} diff --git a/src/ui/moviemodel.h b/src/ui/moviemodel.h new file mode 100644 index 0000000..2652b51 --- /dev/null +++ b/src/ui/moviemodel.h @@ -0,0 +1,59 @@ +// 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 . + +#ifndef MOVIEMODEL_H +#define MOVIEMODEL_H + +#include "data/movie.h" + +#include + +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 diff --git a/src/ui/moviepainter.cpp b/src/ui/moviepainter.cpp new file mode 100644 index 0000000..903e533 --- /dev/null +++ b/src/ui/moviepainter.cpp @@ -0,0 +1,78 @@ +// 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 . + +#include "moviepainter.h" + +#include "data/movie.h" +#include "ratingprovider.h" +#include "ui/styleutils.h" + +#include +#include + +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); +} diff --git a/src/ui/moviepainter.h b/src/ui/moviepainter.h new file mode 100644 index 0000000..822f3ab --- /dev/null +++ b/src/ui/moviepainter.h @@ -0,0 +1,40 @@ +// 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 . + +#ifndef MOVIEPAINTER_H +#define MOVIEPAINTER_H + +#include + +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 diff --git a/src/ui/moviescheduledelegate.cpp b/src/ui/moviescheduledelegate.cpp new file mode 100644 index 0000000..04b4062 --- /dev/null +++ b/src/ui/moviescheduledelegate.cpp @@ -0,0 +1,73 @@ +// 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 . + +#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 + +MovieScheduleDelegate::MovieScheduleDelegate(QWidget *parent) + : QStyledItemDelegate(parent) +{ +} + +void MovieScheduleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + ScheduleEntryItem item = qVariantValue(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(index.data())) { + ScheduleEntryItem item = qVariantValue(index.data()); + if (item.IsScheduleDateItem()) { + return _day_painter.GetSizeHint(option); + } + return _cinema_painter.GetSizeHint(option); + } else { + return QStyledItemDelegate::sizeHint(option, index); + } +} diff --git a/src/ui/moviescheduledelegate.h b/src/ui/moviescheduledelegate.h new file mode 100644 index 0000000..cbfd14a --- /dev/null +++ b/src/ui/moviescheduledelegate.h @@ -0,0 +1,44 @@ +// 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 . + +#ifndef MOVIESCHEDULEDELEGATE_H +#define MOVIESCHEDULEDELEGATE_H + +#include "cinemapainter.h" +#include "daypainter.h" + +#include + +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 diff --git a/src/ui/movieschedulemodel.cpp b/src/ui/movieschedulemodel.cpp new file mode 100644 index 0000000..4d381a1 --- /dev/null +++ b/src/ui/movieschedulemodel.cpp @@ -0,0 +1,82 @@ +// 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 . + +#include "movieschedulemodel.h" + +#include "scheduleentryitem.h" +#include "data/cinemaschedule.h" +#include "utils/assertedlocker.h" + +#include + +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(); +} + diff --git a/src/ui/movieschedulemodel.h b/src/ui/movieschedulemodel.h new file mode 100644 index 0000000..91d9b03 --- /dev/null +++ b/src/ui/movieschedulemodel.h @@ -0,0 +1,55 @@ +// 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 . + +#ifndef MOVIESCHEDULEMODEL_H +#define MOVIESCHEDULEMODEL_H + +#include "data/scheduleentrykey.h" +#include "data/moviekey.h" + +#include + +class CinemaSchedule; + +class MovieScheduleModel : public QAbstractListModel +{ + Q_OBJECT +private: + typedef QList ScheduleDates; + typedef QList 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 diff --git a/src/ui/moviewindow.cpp b/src/ui/moviewindow.cpp new file mode 100644 index 0000000..2991a9e --- /dev/null +++ b/src/ui/moviewindow.cpp @@ -0,0 +1,103 @@ +// 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 . + +#include "moviewindow.h" +#include "ui_moviewindow.h" + +#include "moviescheduledelegate.h" +#include "movieschedulemodel.h" +#include "data/cinemaschedule.h" + +#include +#ifdef Q_WS_MAEMO_5 +#include +#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(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(); + 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(var); + emit ScheduleEntrySelected(schedule_entry_key); +} diff --git a/src/ui/moviewindow.h b/src/ui/moviewindow.h new file mode 100644 index 0000000..b75f30d --- /dev/null +++ b/src/ui/moviewindow.h @@ -0,0 +1,61 @@ +// 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 . + +#ifndef MOVIEWINDOW_H +#define MOVIEWINDOW_H + +#include "abstractmainwindow.h" +#include "data/scheduleentrykey.h" + +#include + +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 diff --git a/src/ui/moviewindow.ui b/src/ui/moviewindow.ui new file mode 100644 index 0000000..e894e0c --- /dev/null +++ b/src/ui/moviewindow.ui @@ -0,0 +1,128 @@ + + + MovieWindow + + + + 0 + 0 + 800 + 480 + + + + Movie + + + + + 4 + + + 16 + + + 8 + + + 16 + + + 8 + + + + + + + + + + 0 + + + 0 + + + + + QListView { + background: rgba(255, 255, 255, 0) +} +QLabel { + background: rgba(255, 255, 255, 0) +} + + + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + + + + 0 + + + 0 + + + + + + + + Qt::AlignCenter + + + true + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + BackgroundLabel + QWidget +
ui/backgroundlabel.h
+ 1 +
+
+ + +
diff --git a/src/ui/ratingprovider.cpp b/src/ui/ratingprovider.cpp new file mode 100644 index 0000000..0fb228d --- /dev/null +++ b/src/ui/ratingprovider.cpp @@ -0,0 +1,53 @@ +// 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 . + +#include "ratingprovider.h" + +#include + +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(); +} diff --git a/src/ui/ratingprovider.h b/src/ui/ratingprovider.h new file mode 100644 index 0000000..ba46463 --- /dev/null +++ b/src/ui/ratingprovider.h @@ -0,0 +1,52 @@ +// 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 . + +#ifndef RATINGPROVIDER_H +#define RATINGPROVIDER_H + +#include + +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 _rating_stars; +}; + +class RatingSingleton +{ +public: + RatingSingleton(); + +private: + RatingProvider _instance; +}; + +#endif // RATINGPROVIDER_H diff --git a/src/ui/scheduleentryitem.cpp b/src/ui/scheduleentryitem.cpp new file mode 100644 index 0000000..ef36641 --- /dev/null +++ b/src/ui/scheduleentryitem.cpp @@ -0,0 +1,64 @@ +// 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 . + +#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; +} diff --git a/src/ui/scheduleentryitem.h b/src/ui/scheduleentryitem.h new file mode 100644 index 0000000..13c4abf --- /dev/null +++ b/src/ui/scheduleentryitem.h @@ -0,0 +1,47 @@ +// 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 . + +#ifndef SCHEDULEENTRYITEM_H +#define SCHEDULEENTRYITEM_H + +#include "data/scheduleentry.h" +#include "data/cinema.h" +#include "data/movie.h" + +#include + +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 diff --git a/src/ui/styleutils.cpp b/src/ui/styleutils.cpp new file mode 100644 index 0000000..82e6a90 --- /dev/null +++ b/src/ui/styleutils.cpp @@ -0,0 +1,107 @@ +// 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 . + +#include "styleutils.h" + +#ifdef Q_WS_MAEMO_5 +#include +#endif + +#include + +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; +} diff --git a/src/ui/styleutils.h b/src/ui/styleutils.h new file mode 100644 index 0000000..a44507b --- /dev/null +++ b/src/ui/styleutils.h @@ -0,0 +1,71 @@ +// 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 . + +#ifndef STYLEUTILS_H +#define STYLEUTILS_H + +#include +#include +#include + +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 diff --git a/src/ui/theaterdelegate.cpp b/src/ui/theaterdelegate.cpp new file mode 100644 index 0000000..0a96c6e --- /dev/null +++ b/src/ui/theaterdelegate.cpp @@ -0,0 +1,52 @@ +// 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 . + +#include "theaterdelegate.h" + +#include "theatermodel.h" +#include "data/cinema.h" + +#include + +TheaterDelegate::TheaterDelegate(QWidget *parent) + : QStyledItemDelegate(parent) +{ +} + +void TheaterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + TheaterItem item = qVariantValue(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(index.data())) { + return _cinema_painter.GetSizeHint(option); + } else { + return QStyledItemDelegate::sizeHint(option, index); + } +} diff --git a/src/ui/theaterdelegate.h b/src/ui/theaterdelegate.h new file mode 100644 index 0000000..8b4cda2 --- /dev/null +++ b/src/ui/theaterdelegate.h @@ -0,0 +1,40 @@ +// 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 . + +#ifndef THEATERDELEGATE_H +#define THEATERDELEGATE_H + +#include "cinemapainter.h" + +#include + +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 diff --git a/src/ui/theatermodel.cpp b/src/ui/theatermodel.cpp new file mode 100644 index 0000000..8b9782d --- /dev/null +++ b/src/ui/theatermodel.cpp @@ -0,0 +1,62 @@ +// 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 . + +#include "theatermodel.h" + +#include "data/cinemaschedule.h" +#include "data/cinema.h" +#include "utils/assertedlocker.h" + +#include + +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(); +} diff --git a/src/ui/theatermodel.h b/src/ui/theatermodel.h new file mode 100644 index 0000000..8f7bc44 --- /dev/null +++ b/src/ui/theatermodel.h @@ -0,0 +1,60 @@ +// 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 . + +#ifndef THEATERMODEL_H +#define THEATERMODEL_H + +#include "data/cinema.h" + +#include +#include + +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 diff --git a/src/ui/theaterscheduledelegate.cpp b/src/ui/theaterscheduledelegate.cpp new file mode 100644 index 0000000..20bea57 --- /dev/null +++ b/src/ui/theaterscheduledelegate.cpp @@ -0,0 +1,73 @@ +// 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 . + +#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 + +TheaterScheduleDelegate::TheaterScheduleDelegate(QWidget *parent) + : QStyledItemDelegate(parent) +{ +} + +void TheaterScheduleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + ScheduleEntryItem item = qVariantValue(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(index.data())) { + ScheduleEntryItem item = qVariantValue(index.data()); + if (item.IsScheduleDateItem()) { + return _day_painter.GetSizeHint(option); + } + return _movie_painter.GetSizeHint(option); + } else { + return QStyledItemDelegate::sizeHint(option, index); + } +} diff --git a/src/ui/theaterscheduledelegate.h b/src/ui/theaterscheduledelegate.h new file mode 100644 index 0000000..ceb42a6 --- /dev/null +++ b/src/ui/theaterscheduledelegate.h @@ -0,0 +1,42 @@ +// 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 . + +#ifndef THEATERSCHEDULEDELEGATE_H +#define THEATERSCHEDULEDELEGATE_H + +#include "moviepainter.h" +#include "daypainter.h" + +#include + +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 diff --git a/src/ui/theaterschedulemodel.cpp b/src/ui/theaterschedulemodel.cpp new file mode 100644 index 0000000..f2ddc64 --- /dev/null +++ b/src/ui/theaterschedulemodel.cpp @@ -0,0 +1,81 @@ +// 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 . + +#include "theaterschedulemodel.h" + +#include "scheduleentryitem.h" +#include "data/cinemaschedule.h" +#include "utils/assertedlocker.h" + +#include + +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(); +} diff --git a/src/ui/theaterschedulemodel.h b/src/ui/theaterschedulemodel.h new file mode 100644 index 0000000..047a140 --- /dev/null +++ b/src/ui/theaterschedulemodel.h @@ -0,0 +1,57 @@ +// 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 . + +#ifndef THEATERSCHEDULEMODEL_H +#define THEATERSCHEDULEMODEL_H + +#include "data/scheduleentrykey.h" +#include "data/cinema.h" +#include "data/movie.h" +#include "data/scheduleentry.h" + +#include + +class CinemaSchedule; + +class TheaterScheduleModel : public QAbstractListModel +{ + Q_OBJECT +private: + typedef QList ScheduleDates; + typedef QList 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 diff --git a/src/ui/theaterwindow.cpp b/src/ui/theaterwindow.cpp new file mode 100644 index 0000000..5b95433 --- /dev/null +++ b/src/ui/theaterwindow.cpp @@ -0,0 +1,103 @@ +// 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 . + +#include "theaterwindow.h" +#include "ui_theaterwindow.h" + +#include "theaterscheduledelegate.h" +#include "theaterschedulemodel.h" +#include "data/cinemaschedule.h" + +#include +#ifdef Q_WS_MAEMO_5 +#include +#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(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(); + 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(var); + emit ScheduleEntrySelected(schedule_entry_key); +} diff --git a/src/ui/theaterwindow.h b/src/ui/theaterwindow.h new file mode 100644 index 0000000..c6f876f --- /dev/null +++ b/src/ui/theaterwindow.h @@ -0,0 +1,61 @@ +// 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 . + +#ifndef THEATERWINDOW_H +#define THEATERWINDOW_H + +#include "abstractmainwindow.h" +#include "data/scheduleentrykey.h" + +#include + +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 diff --git a/src/ui/theaterwindow.ui b/src/ui/theaterwindow.ui new file mode 100644 index 0000000..e8c84d7 --- /dev/null +++ b/src/ui/theaterwindow.ui @@ -0,0 +1,128 @@ + + + TheaterWindow + + + + 0 + 0 + 800 + 480 + + + + Theater + + + + + 4 + + + 16 + + + 8 + + + 16 + + + 8 + + + + + + + + + + 0 + + + 0 + + + + + QListView { + background: rgba(255, 255, 255, 0) +} +QLabel { + background: rgba(255, 255, 255, 0) +} + + + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + + + + 0 + + + 0 + + + + + + + + Qt::AlignCenter + + + true + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + BackgroundLabel + QWidget +
ui/backgroundlabel.h
+ 1 +
+
+ + +
diff --git a/src/ui/uiutils.cpp b/src/ui/uiutils.cpp new file mode 100644 index 0000000..95a5748 --- /dev/null +++ b/src/ui/uiutils.cpp @@ -0,0 +1,46 @@ +// 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 . + +#include "uiutils.h" + +#ifdef Q_WS_MAEMO_5 +#include +#else +#include +#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 +} diff --git a/src/ui/uiutils.h b/src/ui/uiutils.h new file mode 100644 index 0000000..4254036 --- /dev/null +++ b/src/ui/uiutils.h @@ -0,0 +1,36 @@ +// 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 . + +#ifndef UIUTILS_H +#define UIUTILS_H + +#include + +class UiUtils +{ +private: + UiUtils(); + +public: + + static void ShowInformation(const QString &infomsg); + + static void ShowError(const QString &errormsg); + +}; + +#endif // UIUTILS_H diff --git a/src/utils/assertedlock.cpp b/src/utils/assertedlock.cpp new file mode 100644 index 0000000..b1e888f --- /dev/null +++ b/src/utils/assertedlock.cpp @@ -0,0 +1,127 @@ +// 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 . + +#include "assertedlock.h" + +#include +#include + +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 diff --git a/src/utils/assertedlock.h b/src/utils/assertedlock.h new file mode 100644 index 0000000..368c9cd --- /dev/null +++ b/src/utils/assertedlock.h @@ -0,0 +1,94 @@ +// 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 . + +#ifndef ASSERTEDLOCK_H +#define ASSERTEDLOCK_H + +#include +#include +#include + +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 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 diff --git a/src/utils/assertedlocker.cpp b/src/utils/assertedlocker.cpp new file mode 100644 index 0000000..990ea17 --- /dev/null +++ b/src/utils/assertedlocker.cpp @@ -0,0 +1,31 @@ +// 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 . + +#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(); +} diff --git a/src/utils/assertedlocker.h b/src/utils/assertedlocker.h new file mode 100644 index 0000000..b2d3c24 --- /dev/null +++ b/src/utils/assertedlocker.h @@ -0,0 +1,48 @@ +// 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 . + +#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 diff --git a/src/utils/asynccall.cpp b/src/utils/asynccall.cpp new file mode 100644 index 0000000..64e82b7 --- /dev/null +++ b/src/utils/asynccall.cpp @@ -0,0 +1,19 @@ +// 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 . + +#include "asynccall.h" + diff --git a/src/utils/asynccall.h b/src/utils/asynccall.h new file mode 100644 index 0000000..00db5c0 --- /dev/null +++ b/src/utils/asynccall.h @@ -0,0 +1,212 @@ +// 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 . + +#ifndef ASYNCCALL_H +#define ASYNCCALL_H + +#include "asynccallclient.h" +#include "asynccallproxy.h" + +namespace AsyncCallPrivate { + + template + 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 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 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 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 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 +void CallAsync(OBJECT *object, const METHOD &method) +{ + AsyncCallPrivate::AsyncCall0 *async_call = new AsyncCallPrivate::AsyncCall0(object, method); + async_call->CallClient(); +} + +template +void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1) +{ + AsyncCallPrivate::AsyncCall1 *async_call = new AsyncCallPrivate::AsyncCall1(object, method, arg1); + async_call->CallClient(); +} + +template +void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2) +{ + AsyncCallPrivate::AsyncCall2 *async_call = new AsyncCallPrivate::AsyncCall2(object, method, arg1, arg2); + async_call->CallClient(); +} + +template +void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3) +{ + AsyncCallPrivate::AsyncCall3 *async_call = new AsyncCallPrivate::AsyncCall3(object, method, arg1, arg2, arg3); + async_call->CallClient(); +} + +template +void CallAsync(OBJECT *object, const METHOD &method, const ARG1 &arg1, const ARG2 &arg2, const ARG3 &arg3, const ARG4 &arg4) +{ + AsyncCallPrivate::AsyncCall4 *async_call = new AsyncCallPrivate::AsyncCall4(object, method, arg1, arg2, arg3, arg4); + async_call->CallClient(); +} + +#endif // ASYNCCALL_H diff --git a/src/utils/asynccallclient.cpp b/src/utils/asynccallclient.cpp new file mode 100644 index 0000000..d439b0c --- /dev/null +++ b/src/utils/asynccallclient.cpp @@ -0,0 +1,38 @@ +// 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 . + +#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(); + } + +} diff --git a/src/utils/asynccallclient.h b/src/utils/asynccallclient.h new file mode 100644 index 0000000..5670b38 --- /dev/null +++ b/src/utils/asynccallclient.h @@ -0,0 +1,46 @@ +// 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 . + +#ifndef ASYNCCALLCLIENT_H +#define ASYNCCALLCLIENT_H + +#include + +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 diff --git a/src/utils/asynccallproxy.cpp b/src/utils/asynccallproxy.cpp new file mode 100644 index 0000000..6892e20 --- /dev/null +++ b/src/utils/asynccallproxy.cpp @@ -0,0 +1,49 @@ +// 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 . + +#include "asynccallproxy.h" + +#include + +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(); + } + +} diff --git a/src/utils/asynccallproxy.h b/src/utils/asynccallproxy.h new file mode 100644 index 0000000..85ec859 --- /dev/null +++ b/src/utils/asynccallproxy.h @@ -0,0 +1,53 @@ +// 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 . + +#ifndef ASYNCCALLPROXY_H +#define ASYNCCALLPROXY_H + +#include + +namespace AsyncCallPrivate { + + class CallProxyBase { + template friend class AsyncCall0; + template friend class AsyncCall1; + template 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 diff --git a/src/utils/calendar.cpp b/src/utils/calendar.cpp new file mode 100644 index 0000000..b6519f4 --- /dev/null +++ b/src/utils/calendar.cpp @@ -0,0 +1,59 @@ +// 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 . + +#include "calendar.h" + +#ifdef MAEMO_SDK +#include +#include +#include +#include + +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 diff --git a/src/utils/calendar.h b/src/utils/calendar.h new file mode 100644 index 0000000..13bf48c --- /dev/null +++ b/src/utils/calendar.h @@ -0,0 +1,45 @@ +// 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 . + +#ifndef CALENDAR_H +#define CALENDAR_H + +#ifdef MAEMO_SDK + +#include +#include + +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 diff --git a/src/utils/connect.h b/src/utils/connect.h new file mode 100644 index 0000000..ce5a17e --- /dev/null +++ b/src/utils/connect.h @@ -0,0 +1,49 @@ +// 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 . + +#ifndef CONNECT_H +#define CONNECT_H + +#include + +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 diff --git a/src/utils/connectivitymanager.cpp b/src/utils/connectivitymanager.cpp new file mode 100644 index 0000000..73b17a1 --- /dev/null +++ b/src/utils/connectivitymanager.cpp @@ -0,0 +1,123 @@ +// 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 . + +#include "connectivitymanager.h" + +#include +#include +#ifdef MAEMO_SDK +#include +#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(); + + if (!connection_error.isEmpty()) { + emit Error(); + return; + } + + unsigned int connection_status = rep.arguments().value(7).value(); + + 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 +} diff --git a/src/utils/connectivitymanager.h b/src/utils/connectivitymanager.h new file mode 100644 index 0000000..9e87953 --- /dev/null +++ b/src/utils/connectivitymanager.h @@ -0,0 +1,53 @@ +// 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 . + +#ifndef CONNECTIVITYMANAGER_H +#define CONNECTIVITYMANAGER_H + +#include +#include + +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 diff --git a/src/utils/timeutils.cpp b/src/utils/timeutils.cpp new file mode 100644 index 0000000..3597c40 --- /dev/null +++ b/src/utils/timeutils.cpp @@ -0,0 +1,86 @@ +// 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 . + +#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; +} diff --git a/src/utils/timeutils.h b/src/utils/timeutils.h new file mode 100644 index 0000000..92d080d --- /dev/null +++ b/src/utils/timeutils.h @@ -0,0 +1,38 @@ +// 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 . + +#ifndef TIMEUTILS_H +#define TIMEUTILS_H + +#include +#include +#include + +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